import path from "node:path";
import fg from "fast-glob";
import { readPackageJSON } from "pkg-types";
import { checkCompatRange } from "./compat-range";
import { checkErpKitVersion } from "./erp-kit-version";
import type { VersionFinding, WorkspacePackage } from "./shared";
import { checkSkillsVersion } from "./skills-version";

export interface MeasureVersionsResult {
  status: "ok" | "violations";
  violationCount: number;
  findings: VersionFinding[];
}

async function discoverWorkspacePackages(cwd: string, appsRoot: string, modulesRoot: string) {
  const patterns = [
    "package.json",
    `${appsRoot}/*/backend/package.json`,
    `${appsRoot}/*/frontend/package.json`,
    `${modulesRoot}/*/package.json`,
  ];
  const matches = await fg(patterns, {
    cwd,
    onlyFiles: true,
    ignore: ["**/node_modules/**"],
  });
  const packages: WorkspacePackage[] = [];
  const findings: VersionFinding[] = [];
  await Promise.all(
    matches.map(async (relativePath) => {
      try {
        const manifest = await readPackageJSON(path.join(cwd, relativePath));
        packages.push({ relativePath, manifest });
      } catch (err) {
        findings.push({
          severity: "error",
          check: "manifest-parse",
          subject: relativePath,
          message: `Failed to read ${relativePath}: ${err instanceof Error ? err.message : String(err)}`,
        });
      }
    }),
  );
  return { packages, findings };
}

export async function runMeasureVersions({
  appsRoot,
  modulesRoot,
  cwd,
  installedVersion,
}: {
  appsRoot: string;
  modulesRoot: string;
  cwd: string;
  installedVersion: string;
}): Promise<MeasureVersionsResult> {
  const { packages, findings } = await discoverWorkspacePackages(cwd, appsRoot, modulesRoot);
  findings.push(
    ...checkCompatRange(packages),
    ...checkErpKitVersion(packages, installedVersion),
    ...(await checkSkillsVersion(cwd, installedVersion)),
  );

  const violationCount = findings.filter((f) => f.severity !== "info").length;
  return {
    status: violationCount === 0 ? "ok" : "violations",
    violationCount,
    findings,
  };
}
