/**
 * Integration tests for the Delivery Locations admin CRUD (issue #19).
 * Covers create/update/toggle/delete + the manage_delivery_locations guard.
 */
import { vi, describe, it, expect, beforeAll, 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 {
  createDeliveryLocation,
  updateDeliveryLocation,
  toggleDeliveryLocationActive,
  deleteDeliveryLocation,
} from "@/app/(portal)/admin/delivery-locations/actions";
import { makeSession, fd } from "./helpers";

const mockedAuth = vi.mocked(auth);
const PREFIX = "INTTEST_DELLOC_";
let companyId: string;

const asManager = () => mockedAuth.mockResolvedValue(makeSession("u-mgr", "MANAGER") as never);

beforeAll(async () => {
  const company = await db.company.create({ data: { name: `${PREFIX}Co`, code: "ZZDELLOC" } });
  companyId = company.id;
});

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

describe("createDeliveryLocation", () => {
  it("persists a location tied to its company", async () => {
    asManager();
    const result = await createDeliveryLocation(fd({ companyId, address: "Dock 4, Mumbai" }));
    expect(result).toEqual({ ok: true });

    const loc = await db.deliveryLocation.findFirstOrThrow({ where: { companyId, address: "Dock 4, Mumbai" } });
    expect(loc.isActive).toBe(true);
    expect(loc.companyId).toBe(companyId);
  });

  it("requires both a company and an address", async () => {
    asManager();
    expect("error" in (await createDeliveryLocation(fd({ companyId, address: "  " })))).toBe(true);
    expect("error" in (await createDeliveryLocation(fd({ companyId: "", address: "x" })))).toBe(true);
  });

  it("rejects a company that no longer exists", async () => {
    asManager();
    const result = await createDeliveryLocation(fd({ companyId: "nonexistent", address: "x" }));
    expect("error" in result).toBe(true);
  });

  it("refuses callers without manage_delivery_locations", async () => {
    mockedAuth.mockResolvedValue(makeSession("u-tech", "TECHNICAL") as never);
    expect(await createDeliveryLocation(fd({ companyId, address: "x" }))).toEqual({ error: "Forbidden" });
    mockedAuth.mockResolvedValue(makeSession("u-acc", "ACCOUNTS") as never);
    expect(await createDeliveryLocation(fd({ companyId, address: "x" }))).toEqual({ error: "Forbidden" });
  });
});

describe("updateDeliveryLocation / toggle / delete", () => {
  it("edits, toggles active, then deletes a location", async () => {
    asManager();
    await createDeliveryLocation(fd({ companyId, address: "Old Address" }));
    const loc = await db.deliveryLocation.findFirstOrThrow({ where: { companyId, address: "Old Address" } });

    expect(await updateDeliveryLocation(loc.id, fd({ companyId, address: "New Address" }))).toEqual({ ok: true });
    expect((await db.deliveryLocation.findUniqueOrThrow({ where: { id: loc.id } })).address).toBe("New Address");

    expect(await toggleDeliveryLocationActive(loc.id)).toEqual({ ok: true });
    expect((await db.deliveryLocation.findUniqueOrThrow({ where: { id: loc.id } })).isActive).toBe(false);

    expect(await deleteDeliveryLocation(loc.id)).toEqual({ ok: true });
    expect(await db.deliveryLocation.findUnique({ where: { id: loc.id } })).toBeNull();
  });

  it("guards update/toggle/delete behind the permission", async () => {
    mockedAuth.mockResolvedValue(makeSession("u-tech", "TECHNICAL") as never);
    expect(await updateDeliveryLocation("x", fd({ companyId, address: "y" }))).toEqual({ error: "Forbidden" });
    expect(await toggleDeliveryLocationActive("x")).toEqual({ error: "Forbidden" });
    expect(await deleteDeliveryLocation("x")).toEqual({ error: "Forbidden" });
  });
});
