import { basename, dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { createReadonlyStores } from "../../cli/src/commands/verify.js";
import { withFault } from "../../feature/src/adapters/fault/index.js";
import { closureDetectors } from "../../universal/src/primitives/closure/index.js";
import { filesystemDetectors } from "../../universal/src/primitives/filesystem/index.js";
import { isolationDetectors } from "../../universal/src/primitives/isolation/index.js";
import { runUniversal, type UniversalRunPlan } from "../../universal/src/runner.js";
import type { CapabilityProfile } from "../../core/src/sdk/capability.js";
import type { Finding } from "../../schema/src/records/finding.js";
import { lifecycleFixtures, lifecycleFault, lifecycleOracle } from "../fixtures/lifecycle/fixture.js";
import { atomicReplacementKnownBad, filesystemKnownGood, pathContainmentKnownBad } from "../fixtures/filesystem/fixture.js";
import { artifactKnownBad, closureKnownGood, inventoryKnownBad, missingProductionBinding, runtimeReferenceKnownBad } from "../fixtures/closure/fixture.js";
import { readManifest, scoreFindings, type CorpusScore } from "./harness.js";

const FIXTURE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../fixtures");

export type CorpusLifecycleClosureFixtureResult = {
  findings: Finding[];
  cleanFindings: Finding[];
  score: CorpusScore;
};

async function runUniversalFixture(input: {
  fixture: unknown;
  detectors: UniversalRunPlan["detectors"];
  capability: string;
  seed: string;
  runId: string;
}): Promise<Finding[]> {
  const { stores } = await createReadonlyStores("2026-07-25T12:00:00.000Z");
  const capabilities: CapabilityProfile = { platform: "linux", features: { [input.capability]: "available" } };
  const plan: UniversalRunPlan = {
    detectors: input.detectors,
    surfaces: [{
      id: input.capability.endsWith("filesystem") ? "filesystem-surface" : input.capability.endsWith("isolation") ? "isolation-surface" : "closure-surface",
      kind: input.capability.endsWith("filesystem") ? "filesystem" : "package",
      load: () => Promise.resolve(input.fixture),
      witnesses: [
        { kind: "non-vacuity", selection: { matched: 1, expectedEmpty: false } },
        { kind: "precondition", preconditions: [{ name: "fixture-loaded", proven: true }] },
      ],
    }],
    context: { seed: input.seed, clockStart: "2026-07-25T12:00:00.000Z", capabilities },
    stores,
    runId: input.runId,
  };
  return (await runUniversal(plan)).findings;
}

async function runLifecycle(): Promise<{ findings: Finding[]; cleanFindings: Finding[] }> {
  const [leaked, cancellation, isolation, cleanProcess, cleanCancellation, cleanIsolation] = await Promise.all([
    withFault(lifecycleFixtures.leakedProcessDescriptor, lifecycleFault, lifecycleOracle, { runId: "corpus-lifecycle-leaked" }),
    withFault(lifecycleFixtures.cancellationLeak, lifecycleFault, lifecycleOracle, { runId: "corpus-lifecycle-cancellation" }),
    runUniversalFixture({ fixture: lifecycleFixtures.crossRunIsolation, detectors: isolationDetectors, capability: "universal-isolation", seed: "lifecycle-isolation-seed", runId: "corpus-lifecycle-isolation" }),
    withFault(lifecycleFixtures.cleanProcessDescriptor, lifecycleFault, lifecycleOracle, { runId: "corpus-lifecycle-clean-process" }),
    withFault(lifecycleFixtures.cleanCancellation, lifecycleFault, lifecycleOracle, { runId: "corpus-lifecycle-clean-cancellation" }),
    runUniversalFixture({ fixture: lifecycleFixtures.cleanIsolation, detectors: isolationDetectors, capability: "universal-isolation", seed: "lifecycle-clean-isolation-seed", runId: "corpus-lifecycle-clean-isolation" }),
  ]);
  if (leaked.holds || cancellation.holds || !cleanProcess.holds || !cleanCancellation.holds) {
    throw new Error("lifecycle fixture controls did not preserve planted and clean behavior");
  }
  return {
    findings: [...leaked.classified.findings, ...cancellation.classified.findings, ...isolation],
    cleanFindings: [...cleanProcess.classified.findings, ...cleanCancellation.classified.findings, ...cleanIsolation],
  };
}

async function runFilesystem(): Promise<{ findings: Finding[]; cleanFindings: Finding[] }> {
  const [containment, replacement, clean] = await Promise.all([
    runUniversalFixture({ fixture: pathContainmentKnownBad, detectors: filesystemDetectors, capability: "universal-filesystem", seed: "filesystem-containment-seed", runId: "corpus-filesystem-containment" }),
    runUniversalFixture({ fixture: atomicReplacementKnownBad, detectors: filesystemDetectors, capability: "universal-filesystem", seed: "filesystem-replacement-seed", runId: "corpus-filesystem-replacement" }),
    runUniversalFixture({ fixture: filesystemKnownGood, detectors: filesystemDetectors, capability: "universal-filesystem", seed: "filesystem-clean-seed", runId: "corpus-filesystem-clean" }),
  ]);
  return { findings: [...containment, ...replacement], cleanFindings: clean };
}

async function runClosure(): Promise<{ findings: Finding[]; cleanFindings: Finding[] }> {
  const [runtimeReference, inventory, binding, artifact, clean] = await Promise.all([
    runUniversalFixture({ fixture: runtimeReferenceKnownBad, detectors: closureDetectors, capability: "universal-closure", seed: "closure-runtime-reference-seed", runId: "corpus-closure-runtime-reference" }),
    runUniversalFixture({ fixture: inventoryKnownBad, detectors: closureDetectors, capability: "universal-closure", seed: "closure-inventory-seed", runId: "corpus-closure-inventory" }),
    runUniversalFixture({ fixture: missingProductionBinding, detectors: closureDetectors, capability: "universal-closure", seed: "closure-binding-seed", runId: "corpus-closure-binding" }),
    runUniversalFixture({ fixture: artifactKnownBad, detectors: closureDetectors, capability: "universal-closure", seed: "closure-artifact-seed", runId: "corpus-closure-artifact" }),
    runUniversalFixture({ fixture: closureKnownGood, detectors: closureDetectors, capability: "universal-closure", seed: "closure-clean-seed", runId: "corpus-closure-clean" }),
  ]);
  return { findings: [...runtimeReference, ...inventory, ...binding, ...artifact], cleanFindings: clean };
}

export async function runCorpusLifecycleClosureFixture(fixtureDir: string): Promise<CorpusLifecycleClosureFixtureResult> {
  const absoluteFixtureDir = resolve(fixtureDir);
  const fixture = basename(absoluteFixtureDir);
  if (dirname(absoluteFixtureDir) !== FIXTURE_ROOT) {
    throw new Error(`unsupported lifecycle/closure corpus fixture directory: ${fixtureDir}`);
  }
  const manifest = await readManifest(absoluteFixtureDir);
  if (manifest.fixture !== fixture) {
    throw new Error(`lifecycle/closure manifest fixture does not match directory: ${fixtureDir}`);
  }
  const result = fixture === "lifecycle" ? await runLifecycle() : fixture === "filesystem" ? await runFilesystem() : fixture === "closure" ? await runClosure() : undefined;
  if (result === undefined) throw new Error(`unknown lifecycle/closure corpus fixture: ${fixture}`);
  return { ...result, score: scoreFindings(manifest, result.findings) };
}
