import { it, expect, beforeEach, describe } from "vitest";
import { defineContractSuite } from "@repo/core-testing/contract";
import type { I{{pascalCase entity}}Repository } from "../application/repositories/{{kebabCase entity}}.repository.interface.js";
import type { {{pascalCase entity}} } from "../entities/models/{{kebabCase entity}}.js";

/**
 * Known fixtures every implementation's `buildSubject` must pre-seed.
 * Exported so test files can pass them to `Mock{{pascalCase entity}}Repository` or the
 * Payload stub without duplicating definitions.
 */
export const CONTRACT_{{constantCase entity}}_SEED: ReadonlyArray<readonly [string, {{pascalCase entity}}]> = [
  ["seed-1", { id: "seed-1", name: "Seed One" }],
  ["seed-2", { id: "seed-2", name: "Seed Two" }],
];

/**
 * Contract for I{{pascalCase entity}}Repository.
 *
 * The interface exposes only `get{{pascalCase entity}}(id)`. The contract verifies
 * found vs missing behaviour and span emission.
 */
export const {{camelCase entity}}RepositoryContract = defineContractSuite<I{{pascalCase entity}}Repository>(
  "I{{pascalCase entity}}Repository",
  ({ buildSubject, getTracer }) => {
    let repo: I{{pascalCase entity}}Repository;

    beforeEach(async () => {
      repo = await buildSubject();
    });

    it("get{{pascalCase entity}} returns the seeded {{camelCase entity}} when id exists", async () => {
      const result = await repo.get{{pascalCase entity}}("seed-1");
      expect(result).not.toBeNull();
      expect(result?.id).toBe("seed-1");
      expect(typeof result?.name).toBe("string");
    });

    it("get{{pascalCase entity}} returns null for an unknown id", async () => {
      const result = await repo.get{{pascalCase entity}}("does-not-exist");
      expect(result).toBeNull();
    });

    describe("span emission", () => {
      it("get{{pascalCase entity}} emits span '{{camelCase entity}}.get{{pascalCase entity}}' with op=repository", async () => {
        if (!getTracer) return;
        const tracer = getTracer();
        tracer.reset();
        await repo.get{{pascalCase entity}}("seed-1");
        const span = tracer.findSpan("{{camelCase entity}}.get{{pascalCase entity}}");
        expect(span).toBeDefined();
        expect(span!.op).toBe("repository");
      });
    });
  },
);
