import fs from "fs";
import os from "os";
import path from "path";
import { afterEach, describe, expect, it } from "vitest";
import { discoverProject, discoverSuites } from "./discovery.mjs";

const cleanups = [];

afterEach(() => {
  while (cleanups.length > 0) {
    cleanups.pop()();
  }
});

describe("filesystem-discovery", () => {
  it("discovers colocated __testkit__ suites by service root", () => {
    const productDir = fs.mkdtempSync(path.join(os.tmpdir(), "testkit-discovery-"));
    cleanups.push(() => fs.rmSync(productDir, { recursive: true, force: true }));

    writeFile(productDir, "src/api/routes/__testkit__/auth/me.int.testkit.ts");
    writeFile(productDir, "src/api/routes/__testkit__/health/ready.int.testkit.ts");
    writeFile(productDir, "frontend/app/__testkit__/homepage/homepage.pw.testkit.ts");

    const suites = discoverSuites(productDir, {
      api: {
        local: {
          cwd: ".",
        },
      },
      frontend: {
        local: {
          cwd: "frontend",
        },
      },
    });

    expect(suites.api.integration).toEqual([
      {
        name: "auth",
        files: ["src/api/routes/__testkit__/auth/me.int.testkit.ts"],
        framework: "k6",
      },
      {
        name: "health",
        files: ["src/api/routes/__testkit__/health/ready.int.testkit.ts"],
        framework: "k6",
      },
    ]);
    expect(suites.frontend.e2e).toEqual([
      {
        name: "homepage",
        files: ["frontend/app/__testkit__/homepage/homepage.pw.testkit.ts"],
        framework: "playwright",
      },
    ]);
  });

  it("infers the suite from the directory that owns __testkit__", () => {
    const productDir = fs.mkdtempSync(path.join(os.tmpdir(), "testkit-discovery-"));
    cleanups.push(() => fs.rmSync(productDir, { recursive: true, force: true }));

    writeFile(productDir, "src/services/search/__testkit__/query/validation.int.testkit.ts");

    const project = discoverProject(productDir, {
      api: {
        local: {
          cwd: ".",
        },
      },
    });
    expect(project.services.api).toMatchObject({
      name: "api",
      inferredLocalCwd: ".",
    });
    expect(project.suitesByService.api.integration[0]).toMatchObject({
      name: "query",
      files: ["src/services/search/__testkit__/query/validation.int.testkit.ts"],
      framework: "k6",
    });
  });

  it("prefers the deepest matching service root", () => {
    const productDir = fs.mkdtempSync(path.join(os.tmpdir(), "testkit-discovery-"));
    cleanups.push(() => fs.rmSync(productDir, { recursive: true, force: true }));

    writeFile(productDir, "frontend/app/__testkit__/billing/lifecycle.pw.testkit.ts");

    const project = discoverProject(productDir, {
      app: {
        local: {
          cwd: ".",
        },
      },
      frontend: {
        local: {
          cwd: "frontend",
        },
      },
    });

    expect(project.suitesByService.app).toBeUndefined();
    expect(project.suitesByService.frontend.e2e[0]).toMatchObject({
      name: "billing",
      files: ["frontend/app/__testkit__/billing/lifecycle.pw.testkit.ts"],
      framework: "playwright",
    });
  });

  it("fails on legacy files outside __testkit__", () => {
    const productDir = fs.mkdtempSync(path.join(os.tmpdir(), "testkit-discovery-"));
    cleanups.push(() => fs.rmSync(productDir, { recursive: true, force: true }));

    writeFile(productDir, "tests/api/integration/health.int.testkit.ts");

    expect(() =>
      discoverSuites(productDir, {
        api: {
          local: {
            cwd: ".",
          },
        },
      })
    ).toThrow("Legacy test files outside __testkit__");
  });
});

function writeFile(productDir, relativePath) {
  const absolutePath = path.join(productDir, relativePath);
  fs.mkdirSync(path.dirname(absolutePath), { recursive: true });
  fs.writeFileSync(absolutePath, "export {};\n");
}
