import { mkdir, readFile, writeFile } from "node:fs/promises";
import { existsSync } from "node:fs";
import { dirname, join, resolve } from "node:path";
import {
  ContractRegistry,
  checkContractCompatibility,
  type ContractSnapshot,
} from "@wrnexus/validation";

const CURRENT_FILE = "wrnexus.contracts.json";
const BASELINE_FILE = join(".wrnexus", "contracts.json");

function validateSnapshot(value: unknown, source: string): ContractSnapshot {
  const snapshot = value as Partial<ContractSnapshot>;
  if (snapshot?.format !== 1 || !Array.isArray(snapshot.contracts)) {
    throw new Error(`WRN-CONTRACT-FORMAT: ${source} is not a version 1 contract snapshot.`);
  }
  return snapshot as ContractSnapshot;
}

async function currentSnapshot(appRoot: string): Promise<ContractSnapshot> {
  const modulePath = join(appRoot, "app", "contracts.ts");
  if (existsSync(modulePath)) {
    const imported = (await import(`${modulePath}?t=${Date.now()}`)) as {
      default?: ContractRegistry | ContractSnapshot;
      contracts?: ContractRegistry | ContractSnapshot;
    };
    const value = imported.contracts ?? imported.default;
    if (value instanceof ContractRegistry) return value.snapshot();
    return validateSnapshot(value, modulePath);
  }
  const jsonPath = join(appRoot, CURRENT_FILE);
  if (!existsSync(jsonPath)) {
    throw new Error(
      `WRN-CONTRACT-SOURCE: create app/contracts.ts exporting a ContractRegistry, or ${CURRENT_FILE}.`,
    );
  }
  return validateSnapshot(JSON.parse(await readFile(jsonPath, "utf8")), jsonPath);
}

export interface ContractCommandResult {
  ok: boolean;
  issueCount: number;
  baseline: string;
}

export async function runContractsCommand(
  root: string,
  command = "check",
  args: string[] = [],
): Promise<ContractCommandResult> {
  const appRoot = resolve(root);
  const baseline = join(appRoot, BASELINE_FILE);
  const current = await currentSnapshot(appRoot);
  if (command === "snapshot") {
    await mkdir(dirname(baseline), { recursive: true });
    await writeFile(baseline, `${JSON.stringify(current, null, 2)}\n`, "utf8");
    if (args.includes("--json")) console.log(JSON.stringify({ ok: true, baseline }));
    else console.log(`✓ Contract baseline written: ${baseline}`);
    return { ok: true, issueCount: 0, baseline };
  }
  if (command !== "check") throw new Error(`WRN-CONTRACT-COMMAND: unknown command '${command}'.`);
  if (!existsSync(baseline)) {
    throw new Error(`WRN-CONTRACT-BASELINE: no baseline found; run 'wrnexus contracts snapshot'.`);
  }
  const previous = validateSnapshot(JSON.parse(await readFile(baseline, "utf8")), baseline);
  const issues = checkContractCompatibility(previous, current);
  if (args.includes("--json")) {
    console.log(JSON.stringify({ ok: issues.length === 0, issues, baseline }, null, 2));
  } else if (issues.length === 0) {
    console.log(`✓ ${current.contracts.length} contracts are backward compatible.`);
  } else {
    console.error(`Breaking contract changes detected (${issues.length}):`);
    for (const issue of issues) {
      console.error(`  ${issue.code} ${issue.contract}: ${issue.message}`);
      if (issue.consumers.length) console.error(`    Consumers: ${issue.consumers.join(", ")}`);
    }
  }
  return { ok: issues.length === 0, issueCount: issues.length, baseline };
}
