// Plugin Contract Test Plan tests cover plugin contract test plan script behavior.
import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";
import { createPluginContractTestShards } from "../../scripts/lib/plugin-contract-test-plan.mts";
import { expectNoNodeFsScans } from "../../src/test-utils/fs-scan-assertions.js";
import { listGitTrackedFiles } from "../../src/test-utils/repo-files.js";

function listContractTests(rootDir = "src/plugins/contracts"): string[] {
  const files = listGitTrackedFiles({ pathspecs: rootDir });
  expect(files).not.toBeNull();
  return (files ?? []).filter((line) => line.endsWith(".test.ts"));
}

describe("scripts/lib/plugin-contract-test-plan.mts", () => {
  it("keeps manual CI compatible with legacy target refs", () => {
    const workflow = readFileSync(".github/workflows/ci.yml", "utf8");

    // ci.yml imports the plan through the importTargetPlan fallback helper since
    // 7ae5996bb3c so historical target refs without the module keep working.
    expect(workflow).toContain("const pluginContractPlan = await importTargetPlan(");
    expect(workflow).toContain('? "./scripts/lib/plugin-contract-test-plan.mts"');
    expect(workflow).toContain(': "./scripts/lib/plugin-contract-test-plan.mjs",');
    expect(workflow).toContain(
      'typeof pluginContractPlan.createPluginContractTestShards === "function"',
    );
    expect(workflow).toContain("checks-fast-contracts-plugins-legacy");
    expect(workflow).not.toContain(
      "createPluginContractTestShards: () => [\n              createPluginContractTestShards",
    );
  });

  it("splits plugin contracts into focused shards", () => {
    const suffixes = ["a", "b"];

    expect(
      createPluginContractTestShards().map((shard) => ({
        checkName: shard.checkName,
        runtime: shard.runtime,
        task: shard.task,
      })),
    ).toEqual(
      suffixes.map((suffix) => ({
        checkName: `checks-fast-contracts-plugins-${suffix}`,
        runtime: "node",
        task: "contracts-plugins",
      })),
    );
  });

  it("covers every plugin contract test exactly once", () => {
    const actual = createPluginContractTestShards()
      .flatMap((shard) => shard.includePatterns)
      .toSorted((a, b) => a.localeCompare(b));

    expect(actual).toEqual(listContractTests());
    expect(new Set(actual).size).toBe(actual.length);
  });

  it("uses git-tracked files without walking contract directories", () => {
    const payload = expectNoNodeFsScans<{
      files: number;
      shards: number;
    }>(`
      const { createPluginContractTestShards } = await import("./scripts/lib/plugin-contract-test-plan.mts");
      const shards = createPluginContractTestShards();
      return {
        files: shards.reduce((total, shard) => total + shard.includePatterns.length, 0),
        shards: shards.length,
      };
    `);
    expect(payload.shards).toBe(2);
    expect(payload.files).toBeGreaterThan(0);
  });

  it("keeps plugin registration contract files spread across checks", () => {
    for (const shard of createPluginContractTestShards()) {
      const registrationFiles = shard.includePatterns.filter((pattern) =>
        pattern.includes("/plugin-registration."),
      );
      expect(registrationFiles.length).toBeLessThanOrEqual(14);
    }
  });
});
