#!/usr/bin/env node

/**
 * Release Benchmark — SF-07
 *
 * 验证完整链路：Frontend → Backend → Fullstack → Electron → Release
 * 对 PetCare / CRM / Inventory 三个领域执行，输出 release-benchmark-report.md
 */

import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from "node:fs";
import { resolve, dirname, join } from "node:path";
import { execSync } from "node:child_process";
import { fileURLToPath } from "node:url";

const __dirname = dirname(resolve(fileURLToPath(import.meta.url)));
const WORKSPACE = resolve(__dirname, "..");
const BENCH_ROOT = resolve(WORKSPACE, ".benchmark");
const SCRIPTS = resolve(WORKSPACE, "scripts");
const REPORT_PATH = resolve(WORKSPACE, "release-benchmark-report.md");

const DOMAINS = [
  { id: "petcare", input: "做一个宠物护理管理平台，宠物主人可以管理宠物档案、健康日程、日常记录和成长相册" },
  { id: "crm", input: "做一个客户关系管理系统，支持客户管理、销售漏斗、跟进记录和数据分析仪表盘" },
  { id: "inventory", input: "做一个库存管理系统，支持商品入库出库、库存盘点、供应商管理和库存预警" },
];

// ═══════════════════════════════════════════════════════
// Helpers
// ═══════════════════════════════════════════════════════

function cmd(c, opts = {}) {
  try {
    return execSync(c, { cwd: WORKSPACE, encoding: "utf8", ...opts, stdio: opts.stdio ?? "pipe" });
  } catch (e) {
    return { error: e.message, stderr: e.stderr?.toString() || "", stdout: e.stdout?.toString() || "" };
  }
}

function runAgent(agentPath, args) {
  const result = cmd(`node ${agentPath} ${args}`);
  if (result.error) {
    try { return JSON.parse(result.stdout?.trim() || "{}"); } catch { return { error: result.error, stderr: result.stderr }; }
  }
  try { return JSON.parse(result.trim()); } catch { return { raw: result }; }
}

function countFiles(dir) {
  try {
    const r = execSync(`find ${dir} -type f 2>/dev/null | wc -l`, { encoding: "utf8", cwd: WORKSPACE });
    return parseInt(r.trim(), 10);
  } catch { return 0; }
}

function loadJSON(path) {
  try { return JSON.parse(readFileSync(path, "utf8")); } catch { return {}; }
}

// ═══════════════════════════════════════════════════════
// Step 1-4: Full Pipeline (reuse existing agents)
// ═══════════════════════════════════════════════════════

function generateRequirementPackage(domain) {
  console.log(`\n📋 [${domain.id}] Generating RequirementPackage...`);
  const t0 = Date.now();

  const prdOut = join(BENCH_ROOT, domain.id, "prd.json");
  const archOut = join(BENCH_ROOT, domain.id, "arch.json");
  mkdirSync(dirname(prdOut), { recursive: true });

  runAgent(join(SCRIPTS, "project-intake-agent.mjs"), `--input "${domain.input}" --output "${prdOut}"`);
  runAgent(join(SCRIPTS, "architecture-agent.mjs"), `--input "${prdOut}" --output "${archOut}"`);

  const prd = loadJSON(prdOut);
  const elapsed = ((Date.now() - t0) / 1000).toFixed(1);
  console.log(`  ✅ PRD + Architecture (${elapsed}s) — ${prd.projectName || "?"}`);
  return { prd, prdPath: prdOut, archPath: archOut, elapsed: parseFloat(elapsed) };
}

function generateFrontend(domain, prdPath, archPath) {
  console.log(`  🎨 Generating Frontend...`);
  const t0 = Date.now();
  const outDir = join(BENCH_ROOT, domain.id, "frontend");
  runAgent(join(SCRIPTS, "frontend-builder-agent.mjs"), `--prd "${prdPath}" --arch "${archPath}" --output "${outDir}"`);
  const elapsed = ((Date.now() - t0) / 1000).toFixed(1);
  const fc = countFiles(outDir);
  console.log(`  ✅ Frontend (${elapsed}s, ${fc} files)`);
  return { elapsed: parseFloat(elapsed), fileCount: fc };
}

function generateBackend(domain, prdPath, archPath) {
  console.log(`  ⚙️  Generating Backend...`);
  const t0 = Date.now();
  const outDir = join(BENCH_ROOT, domain.id, "backend");
  runAgent(join(SCRIPTS, "backend-builder-agent.mjs"), `--prd "${prdPath}" --arch "${archPath}" --output "${outDir}"`);
  const elapsed = ((Date.now() - t0) / 1000).toFixed(1);
  const fc = countFiles(outDir);
  console.log(`  ✅ Backend (${elapsed}s, ${fc} files)`);
  return { elapsed: parseFloat(elapsed), fileCount: fc };
}

function generateFullstack(domain, prdPath, archPath) {
  console.log(`  🔗 Composing Fullstack...`);
  const t0 = Date.now();
  const outDir = join(BENCH_ROOT, domain.id, "fullstack");
  runAgent(join(SCRIPTS, "fullstack-composer-agent.mjs"), `--prd "${prdPath}" --arch "${archPath}" --output "${outDir}"`);
  const elapsed = ((Date.now() - t0) / 1000).toFixed(1);
  const fc = countFiles(outDir);
  console.log(`  ✅ Fullstack (${elapsed}s, ${fc} files)`);
  return { elapsed: parseFloat(elapsed), fileCount: fc };
}

function generateElectron(domain, prdPath) {
  console.log(`  🖥️  Generating Electron...`);
  const t0 = Date.now();
  const fullstackDir = join(BENCH_ROOT, domain.id, "fullstack");
  const outDir = join(BENCH_ROOT, domain.id, "electron");
  runAgent(join(SCRIPTS, "electron-builder-agent.mjs"), `--input "${fullstackDir}" --output "${outDir}" --prd "${prdPath}"`);
  const elapsed = ((Date.now() - t0) / 1000).toFixed(1);
  const fc = countFiles(outDir);
  console.log(`  ✅ Electron (${elapsed}s, ${fc} files)`);
  return { elapsed: parseFloat(elapsed), fileCount: fc };
}

// ═══════════════════════════════════════════════════════
// Step 5: Release Builder
// ═══════════════════════════════════════════════════════

function generateRelease(domain) {
  console.log(`  📦 Generating Release...`);
  const t0 = Date.now();
  const fullstackDir = join(BENCH_ROOT, domain.id, "fullstack");
  const outDir = join(BENCH_ROOT, domain.id, "release");

  const result = runAgent(join(SCRIPTS, "release-builder-agent.mjs"), `--input "${fullstackDir}" --output "${outDir}"`);
  const elapsed = ((Date.now() - t0) / 1000).toFixed(1);
  const fc = countFiles(outDir);
  console.log(`  ✅ Release (${elapsed}s, ${fc} files)`);
  return { elapsed: parseFloat(elapsed), fileCount: fc, result };
}

// ═══════════════════════════════════════════════════════
// Validation
// ═══════════════════════════════════════════════════════

function validateRelease(domain) {
  const releaseDir = join(BENCH_ROOT, domain.id, "release");
  const checks = {
    hasVersionJson: existsSync(join(releaseDir, "release", "version.json")),
    hasManifestJson: existsSync(join(releaseDir, "release", "manifests", "manifest.json")),
    hasChecksums: existsSync(join(releaseDir, "release", "checksums", "checksums.txt")),
    hasReleaseNotes: existsSync(join(releaseDir, "release", "release-notes", "release-notes.md")),
    hasBuildInfo: existsSync(join(releaseDir, "release", "build-info.json")),
    hasReadme: existsSync(join(releaseDir, "release", "README.md")),
    hasWindowsDir: existsSync(join(releaseDir, "release", "windows")),
    hasMacosDir: existsSync(join(releaseDir, "release", "macos")),
    hasLinuxDir: existsSync(join(releaseDir, "release", "linux")),
  };

  // Validate version.json
  if (checks.hasVersionJson) {
    try {
      const v = JSON.parse(readFileSync(join(releaseDir, "release", "version.json"), "utf8"));
      checks.versionValid = !!(v.name && v.version && v.platforms);
    } catch { checks.versionValid = false; }
  }

  // Validate manifest
  if (checks.hasManifestJson) {
    try {
      const m = JSON.parse(readFileSync(join(releaseDir, "release", "manifests", "manifest.json"), "utf8"));
      checks.manifestValid = !!(m.project && m.version && m.files && m.files.length > 0);
      checks.manifestFileCount = m.files?.length || 0;
    } catch { checks.manifestValid = false; }
  }

  // Validate checksums
  if (checks.hasChecksums) {
    const content = readFileSync(join(releaseDir, "release", "checksums", "checksums.txt"), "utf8");
    const lines = content.trim().split("\n").filter(l => l.length > 0);
    checks.checksumCount = lines.length;
    checks.checksumsValid = lines.every(l => {
      const parts = l.split(/\s+/);
      return parts[0]?.length === 64 && parts[1]?.length > 0;
    });
  }

  // Validate release notes
  if (checks.hasReleaseNotes) {
    const notes = readFileSync(join(releaseDir, "release", "release-notes", "release-notes.md"), "utf8");
    checks.releaseNotesValid = notes.includes("Version") && notes.includes("Features") && notes.includes("Installation");
  }

  // Validate build-info
  if (checks.hasBuildInfo) {
    try {
      const bi = JSON.parse(readFileSync(join(releaseDir, "release", "build-info.json"), "utf8"));
      checks.buildInfoValid = !!(bi.nodeVersion && bi.generatorVersion && bi.buildTime);
    } catch { checks.buildInfoValid = false; }
  }

  // Platform placeholder counts
  if (checks.hasWindowsDir) {
    try { checks.windowsFileCount = readdirSync(join(releaseDir, "release", "windows")).length; } catch { checks.windowsFileCount = 0; }
  }
  if (checks.hasMacosDir) {
    try { checks.macosFileCount = readdirSync(join(releaseDir, "release", "macos")).length; } catch { checks.macosFileCount = 0; }
  }
  if (checks.hasLinuxDir) {
    try { checks.linuxFileCount = readdirSync(join(releaseDir, "release", "linux")).length; } catch { checks.linuxFileCount = 0; }
  }

  checks.allPassed = checks.hasVersionJson && checks.hasManifestJson && checks.hasChecksums &&
    checks.hasReleaseNotes && checks.hasBuildInfo && checks.hasWindowsDir &&
    checks.hasMacosDir && checks.hasLinuxDir && checks.versionValid &&
    checks.manifestValid && checks.checksumsValid && checks.releaseNotesValid && checks.buildInfoValid;

  return checks;
}

// ═══════════════════════════════════════════════════════
// Report
// ═══════════════════════════════════════════════════════

function generateReport(allResults) {
  const lines = [];
  const h = (t) => { lines.push(t); return lines; };

  h(`# Release Benchmark Report — SF-07`);
  h(``);
  h(`> Generated: ${new Date().toISOString()}`);
  h(`> Pipeline: Frontend → Backend → Fullstack → Electron → Release`);
  h(``);

  // ── Domain Results ──
  h(`## Domain Results`);
  h(``);
  h(`| Domain | Release | Manifest | Notes | Result |`);
  h(`|--------|---------|----------|-------|--------|`);

  for (const r of allResults) {
    const rel = r.releaseChecks?.allPassed ? "✅" : "❌";
    const man = r.releaseChecks?.manifestValid ? "✅" : "❌";
    const notes = r.releaseChecks?.releaseNotesValid ? "✅" : "❌";
    const result = r.releaseChecks?.allPassed ? "PASS" : "FAIL";
    h(`| ${r.id} | ${rel} | ${man} | ${notes} | **${result}** |`);
  }
  h(``);

  // ── Release Artifacts ──
  h(`## Release Artifacts`);
  h(``);
  h(`| Domain | Files | Manifest Files | Checksum Lines | Release Notes |`);
  h(`|--------|-------|----------------|----------------|---------------|`);

  for (const r of allResults) {
    const rc = r.releaseChecks || {};
    h(`| ${r.id} | ${r.release?.fileCount || 0} | ${rc.manifestFileCount || 0} | ${rc.checksumCount || 0} | ${rc.hasReleaseNotes ? "✅" : "❌"} |`);
  }
  h(``);

  // ── Pipeline Timing ──
  h(`## Pipeline Timing`);
  h(``);
  h(`| Domain | Frontend | Backend | Fullstack | Electron | Release | Total |`);
  h(`|--------|----------|---------|-----------|----------|---------|-------|`);

  for (const r of allResults) {
    h(`| ${r.id} | ${r.frontend?.elapsed || 0}s | ${r.backend?.elapsed || 0}s | ${r.fullstack?.elapsed || 0}s | ${r.electron?.elapsed || 0}s | ${r.release?.elapsed || 0}s | ${r.totalTime || 0}s |`);
  }
  h(``);

  // ── Validation Details ──
  h(`## Validation Details`);
  h(``);

  for (const r of allResults) {
    h(`### ${r.id}`);
    h(``);
    const rc = r.releaseChecks || {};
    h(`| Check | Status |`);
    h(`|-------|--------|`);
    h(`| version.json | ${rc.hasVersionJson ? "✅" : "❌"} |`);
    h(`| version.json valid | ${rc.versionValid ? "✅" : "❌"} |`);
    h(`| manifest.json | ${rc.hasManifestJson ? "✅" : "❌"} |`);
    h(`| manifest valid | ${rc.manifestValid ? "✅" : "❌"} |`);
    h(`| checksums.txt | ${rc.hasChecksums ? "✅" : "❌"} |`);
    h(`| checksums valid | ${rc.checksumsValid ? "✅" : "❌"} |`);
    h(`| release-notes.md | ${rc.hasReleaseNotes ? "✅" : "❌"} |`);
    h(`| release notes valid | ${rc.releaseNotesValid ? "✅" : "❌"} |`);
    h(`| build-info.json | ${rc.hasBuildInfo ? "✅" : "❌"} |`);
    h(`| build-info valid | ${rc.buildInfoValid ? "✅" : "❌"} |`);
    h(`| windows/ | ${rc.hasWindowsDir ? "✅" : "❌"} (${rc.windowsFileCount || 0} files) |`);
    h(`| macos/ | ${rc.hasMacosDir ? "✅" : "❌"} (${rc.macosFileCount || 0} files) |`);
    h(`| linux/ | ${rc.hasLinuxDir ? "✅" : "❌"} (${rc.linuxFileCount || 0} files) |`);
    h(``);
  }

  // ── Final Status ──
  h(`## Final Status`);
  h(``);

  const passCount = allResults.filter(r => r.releaseChecks?.allPassed).length;
  const total = allResults.length;

  h(`| Metric | Value |`);
  h(`|--------|-------|`);
  h(`| Domains Tested | ${total} |`);
  h(`| Release PASS | ${passCount}/${total} |`);
  h(`| Release FAIL | ${total - passCount}/${total} |`);
  h(``);

  if (passCount === total) {
    h(`🎉 **Release Builder Agent — PASS** (${passCount}/${total})`);
    h(``);
    h(`All domains successfully generated complete release packages.`);
  } else {
    h(`⚠️ **Release Builder Agent — FAIL** (${passCount}/${total})`);
    h(``);
    const failed = allResults.filter(r => !r.releaseChecks?.allPassed);
    h(`Failed domains: ${failed.map(r => r.id).join(", ")}`);
  }
  h(``);

  h(`---`);
  h(`*Report generated by Release Benchmark — SF-07*`);

  return lines.join("\n");
}

// ═══════════════════════════════════════════════════════
// Main
// ═══════════════════════════════════════════════════════

async function main() {
  console.log(`\n🧪 Release Benchmark — SF-07`);
  console.log(`   Testing ${DOMAINS.length} domains`);
  console.log(`   Pipeline: Frontend → Backend → Fullstack → Electron → Release\n`);

  const allResults = [];

  for (const domain of DOMAINS) {
    console.log(`\n${"=".repeat(60)}`);
    console.log(`🏗️  Domain: ${domain.id}`);
    console.log(`${"=".repeat(60)}`);

    const tTotal = Date.now();

    // Steps 1-4: Generate full pipeline
    const { prd, prdPath, archPath, elapsed: reqTime } = generateRequirementPackage(domain);
    const frontend = generateFrontend(domain, prdPath, archPath);
    const backend = generateBackend(domain, prdPath, archPath);
    const fullstack = generateFullstack(domain, prdPath, archPath);
    const electron = generateElectron(domain, prdPath);

    // Step 5: Release
    const release = generateRelease(domain);

    // Validate
    const releaseChecks = validateRelease(domain);

    const totalTime = ((Date.now() - tTotal) / 1000).toFixed(1);

    allResults.push({
      id: domain.id,
      input: domain.input,
      projectName: prd.projectName,
      reqTime,
      frontend,
      backend,
      fullstack,
      electron,
      release,
      releaseChecks,
      totalTime: parseFloat(totalTime),
    });

    console.log(`  ⏱️  Total: ${totalTime}s | Release: ${releaseChecks.allPassed ? "✅ PASS" : "❌ FAIL"}`);
  }

  // Generate report
  const report = generateReport(allResults);
  writeFileSync(REPORT_PATH, report, "utf8");
  console.log(`\n📄 Report written to: ${REPORT_PATH}`);

  // Summary
  const passCount = allResults.filter(r => r.releaseChecks?.allPassed).length;
  console.log(`\n📊 Summary: ${passCount}/${DOMAINS.length} domains PASS`);
  console.log(`   Release Builder: ${passCount === DOMAINS.length ? "✅ PASS" : "❌ FAIL"}`);
}

main().catch(e => {
  console.error("Benchmark failed:", e);
  process.exit(1);
});
