/**
 * Integration tests for company create/update actions.
 * Focus on the behaviour the dedicated add/edit pages rely on:
 *   - createCompany returns the new id (so the create flow can redirect to the edit page)
 *   - fields persist, code is upper-cased, duplicate codes are rejected
 *   - updateCompany edits in place
 *   - both actions are gated by manage_vessels_accounts
 */
import { vi, describe, it, expect, afterAll } from "vitest";

vi.mock("@/auth", () => ({ auth: vi.fn() }));
vi.mock("next/cache", () => ({ revalidatePath: vi.fn() }));

import { auth } from "@/auth";
import { db } from "@/lib/db";
import { createCompany, updateCompany } from "@/app/(portal)/admin/companies/actions";
import { makeSession, fd } from "./helpers";

const mockedAuth = vi.mocked(auth);
const NAME_PREFIX = "INTTEST_CRUD_";

afterAll(async () => {
  await db.company.deleteMany({ where: { name: { startsWith: NAME_PREFIX } } });
});

describe("createCompany", () => {
  it("returns the new id and persists the company (code upper-cased)", async () => {
    mockedAuth.mockResolvedValue(makeSession("u-mgr", "MANAGER") as never);
    const result = await createCompany(fd({
      name: `${NAME_PREFIX}Alpha`,
      code: "zzcrudA",
      gstNumber: "27AAHCP5787B1Z6",
    }));

    expect("id" in result && result.ok).toBe(true);
    if (!("id" in result)) throw new Error(result.error);

    const c = await db.company.findUniqueOrThrow({ where: { id: result.id } });
    expect(c.name).toBe(`${NAME_PREFIX}Alpha`);
    expect(c.code).toBe("ZZCRUDA");
    expect(c.gstNumber).toBe("27AAHCP5787B1Z6");
  });

  it("rejects a duplicate code (case-insensitive)", async () => {
    mockedAuth.mockResolvedValue(makeSession("u-mgr", "MANAGER") as never);
    const first = await createCompany(fd({ name: `${NAME_PREFIX}Dup1`, code: "zzcrudd" }));
    expect("id" in first).toBe(true);

    const second = await createCompany(fd({ name: `${NAME_PREFIX}Dup2`, code: "ZZCRUDD" }));
    expect("error" in second).toBe(true);
  });

  it("refuses callers without manage_vessels_accounts", async () => {
    mockedAuth.mockResolvedValue(makeSession("u-tech", "TECHNICAL") as never);
    const result = await createCompany(fd({ name: `${NAME_PREFIX}Nope`, code: "zzcrudN" }));
    expect(result).toEqual({ error: "Unauthorized" });
  });
});

describe("updateCompany", () => {
  it("edits an existing company in place", async () => {
    mockedAuth.mockResolvedValue(makeSession("u-mgr", "MANAGER") as never);
    const created = await createCompany(fd({ name: `${NAME_PREFIX}Edit`, code: "zzcrudE" }));
    if (!("id" in created)) throw new Error(created.error);

    const result = await updateCompany(fd({
      id: created.id,
      name: `${NAME_PREFIX}Edited`,
      code: "zzcrudE",
      mobile: "+91 99999 00000",
    }));
    expect(result).toEqual({ ok: true });

    const c = await db.company.findUniqueOrThrow({ where: { id: created.id } });
    expect(c.name).toBe(`${NAME_PREFIX}Edited`);
    expect(c.mobile).toBe("+91 99999 00000");
  });

  it("refuses callers without manage_vessels_accounts", async () => {
    mockedAuth.mockResolvedValue(makeSession("u-tech", "TECHNICAL") as never);
    const result = await updateCompany(fd({ id: "whatever", name: "x", code: "ZZX" }));
    expect(result).toEqual({ error: "Unauthorized" });
  });
});
