import { describe, it, expect, vi } from "vitest";
import { RecordingTracer } from "@repo/core-testing/instrumentation";
import { HeaderRepository } from "@/infrastructure/repositories/header.repository";
import { headerRepositoryContract, CONTRACT_HEADER_SEED } from "@/__contracts__/header-repository.contract";
import { stubPayloadConfig } from "@repo/core-testing/payload/stub-config";

// ---------------------------------------------------------------------------
// In-memory Payload stub for header (Global)
// ---------------------------------------------------------------------------

function buildHeaderStub(overrides?: Record<string, unknown>) {
  return {
    findGlobal: vi.fn(async () => {
      return { ...CONTRACT_HEADER_SEED, ...overrides };
    }),
  };
}

vi.mock("payload", () => ({
  getPayload: vi.fn(),
}));

// ---------------------------------------------------------------------------
// Contract suite
// ---------------------------------------------------------------------------

describe("HeaderRepository", () => {
  describe("contract", () => {
    const tracer = new RecordingTracer();
    headerRepositoryContract.run(
      async () => {
        const stub = buildHeaderStub();
        const { getPayload } = await import("payload");
        (getPayload as ReturnType<typeof vi.fn>).mockResolvedValue(stub);
        return new HeaderRepository(stubPayloadConfig, tracer);
      },
      { tracer: () => tracer },
    );
  });

  // ---------------------------------------------------------------------------
  // Logo field branch coverage
  // ---------------------------------------------------------------------------

  it("resolves logoId from a relation object ({ id })", async () => {
    const stub = buildHeaderStub({ logo: { id: "abc-123" } });
    const { getPayload } = await import("payload");
    (getPayload as ReturnType<typeof vi.fn>).mockResolvedValue(stub);

    const repo = new HeaderRepository(stubPayloadConfig);
    const header = await repo.getHeader();

    expect(header.logoId).toBe("abc-123");
  });

  it("resolves logoId from a scalar id (string)", async () => {
    const stub = buildHeaderStub({ logo: "scalar-id" });
    const { getPayload } = await import("payload");
    (getPayload as ReturnType<typeof vi.fn>).mockResolvedValue(stub);

    const repo = new HeaderRepository(stubPayloadConfig);
    const header = await repo.getHeader();

    expect(header.logoId).toBe("scalar-id");
  });

  it("resolves logoId as undefined when logo is null", async () => {
    const stub = buildHeaderStub({ logo: null });
    const { getPayload } = await import("payload");
    (getPayload as ReturnType<typeof vi.fn>).mockResolvedValue(stub);

    const repo = new HeaderRepository(stubPayloadConfig);
    const header = await repo.getHeader();

    expect(header.logoId).toBeUndefined();
  });

  it("maps null item fields to empty strings and false", async () => {
    const stub = {
      findGlobal: vi.fn(async () => ({
        items: [{ label: null, href: null, external: null }],
      })),
    };
    const { getPayload } = await import("payload");
    (getPayload as ReturnType<typeof vi.fn>).mockResolvedValue(stub);

    const repo = new HeaderRepository(stubPayloadConfig);
    const header = await repo.getHeader();

    expect(header.items[0]?.label).toBe("");
    expect(header.items[0]?.href).toBe("");
    expect(header.items[0]?.external).toBe(false);
  });
});
