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

import { WP4_07_PERFORMANCE_BUDGETS } from "../tests/visual-performance/wp4-07-fixture.mjs";

const evidenceIndex = process.argv.indexOf("--evidence");
const phaseIndex = process.argv.indexOf("--phase");
const evidenceDirectory = resolve(evidenceIndex >= 0 ? process.argv[evidenceIndex + 1] : "");
const phase = phaseIndex >= 0 ? process.argv[phaseIndex + 1] : "green";
if (evidenceIndex < 0 || !process.argv[evidenceIndex + 1] || !["green", "red"].includes(phase)) throw new Error("Usage: --evidence <directory> [--phase red|green]");

function read(browser, filename) {
  const path = resolve(evidenceDirectory, browser, filename);
  if (!existsSync(path)) throw new Error(`missing ${browser}/${filename}`);
  return JSON.parse(readFileSync(path, "utf8"));
}

const browserResults = {};
let greenInputsEligible = true;
for (const browser of ["chrome", "edge"]) {
  const raw = read(browser, "performance-raw.json");
  const memory = read(browser, "memory.json");
  const dom = read(browser, "dom-count.json");
  const environment = read(browser, "environment.json");
  greenInputsEligible = greenInputsEligible && raw.eligible_for_green === true && raw.harness_mode === "real_archive";
  if (raw.interaction.length !== 5 || raw.autosave_serialization.length !== 5 || raw.export_1080x1920.length !== 5 || raw.editor_reopen.samples_ms.length !== 5) {
    throw new Error(`${browser} did not retain exactly five measured samples per budget`);
  }
  if (raw.interaction.some((run) => run.duration_ms < WP4_07_PERFORMANCE_BUDGETS.interaction_duration_ms)) {
    throw new Error(`${browser} shortened a ten-second interaction measurement`);
  }
  const checks = {
    autosave_serialization: raw.autosave_serialization.every((run) => run.p95_ms <= WP4_07_PERFORMANCE_BUDGETS.autosave_serialization_p95_ms_max),
    canvas_frame: raw.interaction.every((run) => run.frame_p95_ms <= WP4_07_PERFORMANCE_BUDGETS.canvas_frame_p95_ms_max),
    continuous_unresponsive: raw.interaction.every((run) => run.frame_max_ms < WP4_07_PERFORMANCE_BUDGETS.continuous_unresponsive_ms_max_exclusive),
    dom_bounded: dom.bounded_by_viewport_and_two_screens === true && dom.top_count < dom.catalog_count && dom.bottom_count < dom.catalog_count,
    editor_reopen: raw.editor_reopen.max_ms <= WP4_07_PERFORMANCE_BUDGETS.editor_reopen_ms_max,
    export_duration: raw.export_1080x1920.every((run) => run.duration_ms <= WP4_07_PERFORMANCE_BUDGETS.export_1080x1920_ms_max),
    export_failure_isolated: raw.export_failure.observed_error === "export_asset_unavailable"
      && JSON.stringify(raw.export_failure.saves_before) === JSON.stringify(raw.export_failure.saves_after),
    export_memory: memory.export_peak_additional_bytes.every((value) => value <= WP4_07_PERFORMANCE_BUDGETS.export_peak_additional_bytes_max),
    long_task: raw.interaction.every((run) => run.long_task_max_ms <= WP4_07_PERFORMANCE_BUDGETS.long_task_ms_max),
    pointer_to_frame: raw.interaction.every((run) => run.pointer_to_frame_p95_ms <= WP4_07_PERFORMANCE_BUDGETS.pointer_to_frame_p95_ms_max),
  };
  browserResults[browser] = {
    checks,
    environment,
    fixture_sha256: raw.fixture_sha256,
    metrics: {
      autosave_serialization: raw.autosave_serialization,
      editor_reopen: raw.editor_reopen,
      export_1080x1920: raw.export_1080x1920,
      interaction: raw.interaction,
    },
    status: Object.values(checks).every(Boolean) ? "within_budget" : "budget_exceeded",
  };
}
const passed = Object.values(browserResults).every((result) => result.status === "within_budget");
const report = {
  browsers: browserResults,
  eligible_for_green: phase === "green" && greenInputsEligible,
  normative_budgets: WP4_07_PERFORMANCE_BUDGETS,
  phase,
  status: passed ? "within_budget" : "budget_exceeded",
};
writeFileSync(resolve(evidenceDirectory, "performance.json"), `${JSON.stringify(report, null, 2)}\n`);
writeFileSync(resolve(evidenceDirectory, "memory.json"), `${JSON.stringify({
  browsers: Object.fromEntries(["chrome", "edge"].map((browser) => [browser, read(browser, "memory.json")])),
  limit_bytes: WP4_07_PERFORMANCE_BUDGETS.export_peak_additional_bytes_max,
}, null, 2)}\n`);
writeFileSync(resolve(evidenceDirectory, "dom-count.json"), `${JSON.stringify({
  browsers: Object.fromEntries(["chrome", "edge"].map((browser) => [browser, read(browser, "dom-count.json")])),
  required_catalog_count: 1_407,
}, null, 2)}\n`);
writeFileSync(resolve(evidenceDirectory, "environment.json"), `${JSON.stringify({
  browsers: Object.fromEntries(["chrome", "edge"].map((browser) => [browser, read(browser, "environment.json")])),
  fixture_hashes_match: browserResults.chrome.fixture_sha256 === browserResults.edge.fixture_sha256,
}, null, 2)}\n`);
console.log(JSON.stringify({ browser_statuses: Object.fromEntries(Object.entries(browserResults).map(([name, result]) => [name, result.status])), phase, status: report.status }, null, 2));
if (phase === "green" && (!greenInputsEligible || !passed)) process.exit(1);
