import { describe, vi, beforeEach } from "vitest";
import { RecordingTracer } from "@repo/core-testing/instrumentation";
import { UsersRepository } from "@/infrastructure/repositories/users.repository";
import { usersRepositoryContract } from "@/__contracts__/users-repository.contract";
import { stubPayloadConfig } from "@repo/core-testing/payload/stub-config";

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

function buildPayloadStub() {
  const store = new Map<string, Record<string, unknown>>();

  return {
    create: vi.fn(
      async ({
        data,
      }: {
        collection: string;
        data: Record<string, unknown>;
        overrideAccess?: boolean;
      }) => {
        const doc = { ...data };
        store.set(String(doc.id), doc);
        return doc;
      },
    ),
    find: vi.fn(
      async ({
        where,
      }: {
        collection: string;
        where?: { username?: { equals: string } };
        limit?: number;
        overrideAccess?: boolean;
      }) => {
        const all = Array.from(store.values());
        if (where?.username?.equals) {
          return { docs: all.filter((u) => u.username === where.username?.equals) };
        }
        return { docs: all };
      },
    ),
    findByID: vi.fn(
      async ({ id }: { collection: string; id: string; overrideAccess?: boolean }) => {
        return store.get(String(id)) ?? null;
      },
    ),
  };
}

describe("UsersRepository", () => {
  describe("contract", () => {
    const tracer = new RecordingTracer();

    beforeEach(() => {
      vi.clearAllMocks();
    });

    usersRepositoryContract.run(
      async () => {
        const stub = buildPayloadStub();
        const { getPayload } = await import("payload");
        (getPayload as ReturnType<typeof vi.fn>).mockResolvedValue(stub);
        return new UsersRepository(stubPayloadConfig, tracer);
      },
      { tracer: () => tracer },
    );
  });
});
