import { existsSync, readFileSync } from "node:fs";
import { join, resolve } from "node:path";

interface BuildReport {
  frameworkVersion: string;
  generatedAt: string;
  adapter: string;
  routes: Array<{
    path: string;
    source: string;
    sourceBytes: number;
    dynamicParams: string[];
    optimization?: {
      staticNodes: number;
      reactiveRegions: number;
      eliminatedBranches: number;
      unusedState: string[];
      unusedHandlers: string[];
      constantProps: string[];
      unusedLocalCssClasses: string[];
      batchableStateUpdates: number;
      memoizableComponents: string[];
      preloadDependencies: string[];
      serverOnlyModules: string[];
    };
  }>;
  assets: Array<{ file: string; bytes: number }>;
  measurements: Record<string, number>;
  budgetViolations: Array<{ metric: string; budget: number; actual: number; overBy: number }>;
}

function bytes(value: number): string {
  if (value < 1024) return `${value} B`;
  if (value < 1024 * 1024) return `${(value / 1024).toFixed(1)} KB`;
  return `${(value / 1024 / 1024).toFixed(2)} MB`;
}

export function runAnalyze(appRoot: string, args: string[]): boolean {
  const root = resolve(appRoot);
  const path = join(root, "dist", "build-report.json");
  if (!existsSync(path)) {
    console.error("WRN-BUILD-REPORT-MISSING: run `wrnexus build` before `wrnexus analyze`.");
    return false;
  }
  const report = JSON.parse(readFileSync(path, "utf8")) as BuildReport;
  if (args.includes("--json")) {
    console.log(JSON.stringify(report, null, 2));
    return report.budgetViolations.length === 0;
  }

  console.log(`WRNexus build analysis (${report.frameworkVersion})`);
  console.log(`  Generated: ${report.generatedAt}`);
  console.log(`  Adapter:   ${report.adapter}`);
  console.log(`  Routes:    ${report.routes.length}`);
  console.log("\nMeasurements:");
  for (const [metric, value] of Object.entries(report.measurements)) {
    console.log(`  ${metric.padEnd(18)} ${bytes(value)}`);
  }
  console.log("\nLargest assets:");
  for (const asset of report.assets.slice(0, 12)) {
    console.log(`  ${bytes(asset.bytes).padStart(10)}  ${asset.file}`);
  }
  console.log("\nCompiler optimizations:");
  for (const route of report.routes.filter((item) => item.optimization)) {
    const optimization = route.optimization!;
    console.log(
      `  ${route.path}: ${optimization.staticNodes} static nodes, ${optimization.reactiveRegions} reactive regions, ${optimization.eliminatedBranches} branches removed`,
    );
    if (
      optimization.unusedState.length ||
      optimization.unusedHandlers.length ||
      optimization.unusedLocalCssClasses.length
    )
      console.log(
        `    candidates: ${[...optimization.unusedState, ...optimization.unusedHandlers, ...optimization.unusedLocalCssClasses].join(", ")}`,
      );
  }
  if (report.budgetViolations.length) {
    console.log("\nBudget violations:");
    for (const violation of report.budgetViolations) {
      console.log(
        `  ✗ ${violation.metric}: ${bytes(violation.actual)} > ${bytes(violation.budget)}`,
      );
    }
  } else {
    console.log("\n  ✓ No configured performance budget violations.");
  }
  return report.budgetViolations.length === 0;
}
