import "reflect-metadata";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { NoopTracer, NoopLogger } from "@repo/core-shared/instrumentation";
import { bindDevSeed{{pascalCase name}} } from "@/di/bind-dev-seed";
import { {{camelCase name}}Container } from "@/di/container";
import { {{constantCase name}}_SYMBOLS } from "@/di/symbols";
import { Mock{{pascalCase entity}}Repository } from "@/infrastructure/repositories/{{kebabCase entity}}.repository.mock";
import type { I{{pascalCase entity}}Repository } from "@/application/repositories/{{kebabCase entity}}.repository.interface";

const noop = { tracer: new NoopTracer(), logger: new NoopLogger() };

describe("bindDevSeed{{pascalCase name}}", () => {
  beforeEach(() => {
    if ({{camelCase name}}Container.isBound({{constantCase name}}_SYMBOLS.I{{pascalCase entity}}Repository)) {
      {{camelCase name}}Container.unbind({{constantCase name}}_SYMBOLS.I{{pascalCase entity}}Repository);
    }
    {{camelCase name}}Container
      .bind<I{{pascalCase entity}}Repository>({{constantCase name}}_SYMBOLS.I{{pascalCase entity}}Repository)
      .to(Mock{{pascalCase entity}}Repository);
  });

  afterEach(() => {
    if ({{camelCase name}}Container.isBound({{constantCase name}}_SYMBOLS.I{{pascalCase entity}}Repository)) {
      {{camelCase name}}Container.unbind({{constantCase name}}_SYMBOLS.I{{pascalCase entity}}Repository);
    }
    {{camelCase name}}Container
      .bind<I{{pascalCase entity}}Repository>({{constantCase name}}_SYMBOLS.I{{pascalCase entity}}Repository)
      .to(Mock{{pascalCase entity}}Repository);
  });

  it("populates the repository with the dev seed", async () => {
    await bindDevSeed{{pascalCase name}}(noop);

    const repo = {{camelCase name}}Container.get<I{{pascalCase entity}}Repository>(
      {{constantCase name}}_SYMBOLS.I{{pascalCase entity}}Repository,
    );
    const found = await repo.get{{pascalCase entity}}("dev-1");

    expect(found).not.toBeNull();
    expect(found?.id).toBe("dev-1");
  });

  it("is idempotent — calling twice rebuilds a fresh populated repo", async () => {
    await bindDevSeed{{pascalCase name}}(noop);
    const before = {{camelCase name}}Container.get<I{{pascalCase entity}}Repository>(
      {{constantCase name}}_SYMBOLS.I{{pascalCase entity}}Repository,
    );

    await bindDevSeed{{pascalCase name}}(noop);
    const after = {{camelCase name}}Container.get<I{{pascalCase entity}}Repository>(
      {{constantCase name}}_SYMBOLS.I{{pascalCase entity}}Repository,
    );

    expect(after).not.toBe(before);
  });
});
