/**
 * Integration test for the server-side PII masking on the crew profile page.
 * Identity-document numbers (Aadhaar/PAN) must be masked BEFORE they cross to the
 * client component — full only for Accounts/SuperUser (Crewing-Implementation-Spec
 * §6 / Roles-and-Permissions §3). We invoke the server component and inspect the
 * props it hands to <CrewProfile>, so a regression that passes raw numbers to the
 * client is caught here.
 */
import { vi, describe, it, expect, beforeAll, afterAll, afterEach } from "vitest";
import React from "react";

// The integration runner compiles the page's JSX to classic React.createElement
// without injecting React; provide it so invoking the server component works.
(globalThis as unknown as { React: typeof React }).React = React;

vi.mock("@/auth", () => ({ auth: vi.fn() }));
vi.mock("@/lib/feature-flags", () => ({ CREWING_ENABLED: true, INVENTORY_ENABLED: true }));
vi.mock("next/navigation", () => ({ redirect: vi.fn(), notFound: vi.fn() }));
// The client component is irrelevant to this test — we read element.props directly.
vi.mock("@/app/(portal)/crewing/crew/[id]/crew-profile", () => ({ CrewProfile: () => null }));

import { auth } from "@/auth";
import { db } from "@/lib/db";
import CrewProfilePage from "@/app/(portal)/crewing/crew/[id]/page";
import { makeSession } from "./helpers";
import type { Role } from "@prisma/client";

const AADHAAR = "123456789012";
const PAN = "ABCDE1234F";

let crewId: string;
const as = (role: Role) =>
  vi.mocked(auth as unknown as () => Promise<unknown>).mockResolvedValue(makeSession(`u-${role}`, role));

// Pull the documents prop the page would pass to the client component.
async function docsFor(role: Role) {
  as(role);
  const element = (await CrewProfilePage({ params: Promise.resolve({ id: crewId }) })) as {
    props: { documents: Array<{ docType: string; number: string | null }> };
  };
  return element.props.documents;
}
const numberFor = (docs: Array<{ docType: string; number: string | null }>, docType: string) =>
  docs.find((d) => d.docType === docType)?.number ?? null;

beforeAll(async () => {
  const c = await db.crewMember.create({
    data: { name: "PII Crew", status: "EMPLOYEE", type: "NEW", source: "CAREERS", employeeId: `CRW-PII${Date.now() % 100000}` },
  });
  crewId = c.id;
  await db.seafarerDocument.createMany({
    data: [
      { crewMemberId: c.id, docType: "AADHAAR", number: AADHAAR },
      { crewMemberId: c.id, docType: "PAN", number: PAN },
      { crewMemberId: c.id, docType: "PASSPORT", number: "P1234567" },
    ],
  });
});

afterEach(() => vi.clearAllMocks());

afterAll(async () => {
  await db.seafarerDocument.deleteMany({ where: { crewMemberId: crewId } });
  await db.crewMember.deleteMany({ where: { id: crewId } });
});

describe("crew profile — identity-document masking (server-side)", () => {
  it("masks Aadhaar/PAN for a MANAGER", async () => {
    const docs = await docsFor("MANAGER");
    expect(numberFor(docs, "AADHAAR")).toBe("•••• 9012");
    expect(numberFor(docs, "PAN")).toBe("•••• 234F");
    // Non-identity documents are not restricted.
    expect(numberFor(docs, "PASSPORT")).toBe("P1234567");
  });

  it("masks Aadhaar/PAN for SITE_STAFF and the MPO too", async () => {
    expect(numberFor(await docsFor("SITE_STAFF"), "AADHAAR")).toBe("•••• 9012");
    expect(numberFor(await docsFor("MANNING"), "PAN")).toBe("•••• 234F");
  });

  it("shows Aadhaar/PAN in full to ACCOUNTS and SUPERUSER", async () => {
    const acc = await docsFor("ACCOUNTS");
    expect(numberFor(acc, "AADHAAR")).toBe(AADHAAR);
    expect(numberFor(acc, "PAN")).toBe(PAN);
    expect(numberFor(await docsFor("SUPERUSER"), "AADHAAR")).toBe(AADHAAR);
  });
});
