import { describe, it } from "vitest";
import { RuleTester } from "eslint";
import path from "node:path";
import os from "node:os";
import fs from "node:fs";
import rule from "./feature-must-have-manifest.js";

function makeFeatureFixture({ withManifest }) {
  const repoRoot = fs.mkdtempSync(path.join(os.tmpdir(), "fmm-"));
  const featureDir = path.join(repoRoot, "packages", "demo");
  fs.mkdirSync(path.join(featureDir, "src", "application", "use-cases"), { recursive: true });
  if (withManifest) {
    fs.writeFileSync(
      path.join(featureDir, "src", "feature.manifest.ts"),
      `export const demoManifest = defineFeature({ name: "demo", requiredCores: [], useCases: {}, realtimeChannels: [], jobs: [] } as const);`,
    );
  }
  const useCaseFile = path.join(featureDir, "src", "application", "use-cases", "do-thing.use-case.ts");
  fs.writeFileSync(useCaseFile, `export const doThingUseCase = () => async () => {};`);
  return { repoRoot, useCaseFile };
}

const tester = new RuleTester({ languageOptions: { ecmaVersion: "latest", sourceType: "module" } });

describe("feature-must-have-manifest", () => {
  it("passes when the feature has a manifest", () => {
    const { repoRoot, useCaseFile } = makeFeatureFixture({ withManifest: true });
    tester.run("feature-must-have-manifest", rule, {
      valid: [
        {
          filename: useCaseFile,
          code: fs.readFileSync(useCaseFile, "utf8"),
          options: [{ repoRoot }],
        },
      ],
      invalid: [],
    });
  });

  it("fires when the feature has no manifest", () => {
    const { repoRoot, useCaseFile } = makeFeatureFixture({ withManifest: false });
    tester.run("feature-must-have-manifest", rule, {
      valid: [],
      invalid: [
        {
          filename: useCaseFile,
          code: fs.readFileSync(useCaseFile, "utf8"),
          options: [{ repoRoot }],
          errors: [{ messageId: "missingManifest" }],
        },
      ],
    });
  });
});
