#!/usr/bin/env node

/**
 * Domain Benchmark Suite — runs 10 domains through full pipeline.
 * 
 * For each domain:
 *   1. Generate fullstack project
 *   2. npm install + tsc build
 *   3. Start server, test Health, Auth, CRUD
 * 
 * Output: benchmark-report.md
 */

import { execSync, spawn } from "node:child_process";
import { existsSync, rmSync, readFileSync, writeFileSync } from "node:fs";
import { resolve, dirname } from "node:path";
import { fileURLToPath } from "node:url";
import * as http from "node:http";

const __dirname = dirname(resolve(fileURLToPath(import.meta.url)));
const WORKSPACE = resolve(__dirname, "..", "..");
const BENCH_DIR = resolve(WORKSPACE, ".tmp-benchmark");

const DOMAINS = [
  {
    name: "PetCare", label: "宠物管理",
    prd: { projectName: "PetCare", domain: "pet", summary: "宠物健康管理应用", features: [{ name: "宠物档案", priority: "P0" }], pages: [{ name: "首页", route: "/home" }], personas: [], userStories: [] },
    arch: { databaseSchema: [{ table: "pets", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "owner_id", type: "TEXT", constraints: "NOT NULL, FK → users.id" }, { name: "name", type: "TEXT", constraints: "NOT NULL" }, { name: "species", type: "TEXT" }, { name: "breed", type: "TEXT" }, { name: "weight_kg", type: "REAL" }, { name: "created_at", type: "TEXT" }] }, { table: "schedules", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "pet_id", type: "TEXT", constraints: "NOT NULL, FK → pets.id" }, { name: "type", type: "TEXT", constraints: "NOT NULL" }, { name: "title", type: "TEXT", constraints: "NOT NULL" }, { name: "scheduled_at", type: "TEXT", constraints: "NOT NULL" }, { name: "completed", type: "INTEGER" }, { name: "created_at", type: "TEXT" }] }, { table: "daily_logs", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "pet_id", type: "TEXT", constraints: "NOT NULL, FK → pets.id" }, { name: "category", type: "TEXT", constraints: "NOT NULL" }, { name: "value", type: "TEXT", constraints: "NOT NULL" }, { name: "logged_at", type: "TEXT" }] }], apiDesign: [{ resource: "pets", basePath: "/api/pets", endpoints: [{ method: "GET", path: "/api/pets" }, { method: "POST", path: "/api/pets" }, { method: "GET", path: "/api/pets/:id" }, { method: "PUT", path: "/api/pets/:id" }, { method: "DELETE", path: "/api/pets/:id" }] }] },
  },
  {
    name: "CRM", label: "客户关系管理",
    prd: { projectName: "CRM", domain: "enterprise", summary: "CRM系统", features: [{ name: "客户管理", priority: "P0" }], pages: [{ name: "首页", route: "/home" }], personas: [], userStories: [] },
    arch: { databaseSchema: [{ table: "customers", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "owner_id", type: "TEXT", constraints: "NOT NULL, FK → users.id" }, { name: "name", type: "TEXT", constraints: "NOT NULL" }, { name: "company", type: "TEXT" }, { name: "email", type: "TEXT" }, { name: "phone", type: "TEXT" }, { name: "status", type: "TEXT" }, { name: "created_at", type: "TEXT" }] }, { table: "deals", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "customer_id", type: "TEXT", constraints: "NOT NULL, FK → customers.id" }, { name: "title", type: "TEXT", constraints: "NOT NULL" }, { name: "amount", type: "REAL" }, { name: "stage", type: "TEXT" }, { name: "created_at", type: "TEXT" }] }, { table: "activities", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "customer_id", type: "TEXT", constraints: "NOT NULL, FK → customers.id" }, { name: "type", type: "TEXT", constraints: "NOT NULL" }, { name: "note", type: "TEXT", constraints: "NOT NULL" }, { name: "created_at", type: "TEXT" }] }], apiDesign: [{ resource: "customers", basePath: "/api/customers", endpoints: [{ method: "GET", path: "/api/customers" }, { method: "POST", path: "/api/customers" }, { method: "GET", path: "/api/customers/:id" }, { method: "PUT", path: "/api/customers/:id" }, { method: "DELETE", path: "/api/customers/:id" }] }] },
  },
  {
    name: "Inventory", label: "库存管理",
    prd: { projectName: "Inventory", domain: "ecommerce", summary: "库存管理", features: [{ name: "商品管理", priority: "P0" }], pages: [{ name: "首页", route: "/home" }], personas: [], userStories: [] },
    arch: { databaseSchema: [{ table: "products", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "owner_id", type: "TEXT", constraints: "NOT NULL, FK → users.id" }, { name: "name", type: "TEXT", constraints: "NOT NULL" }, { name: "sku", type: "TEXT" }, { name: "quantity", type: "INTEGER" }, { name: "price", type: "REAL" }, { name: "created_at", type: "TEXT" }] }, { table: "transactions", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "product_id", type: "TEXT", constraints: "NOT NULL, FK → products.id" }, { name: "type", type: "TEXT", constraints: "NOT NULL" }, { name: "quantity", type: "INTEGER", constraints: "NOT NULL" }, { name: "note", type: "TEXT" }, { name: "created_at", type: "TEXT" }] }], apiDesign: [{ resource: "products", basePath: "/api/products", endpoints: [{ method: "GET", path: "/api/products" }, { method: "POST", path: "/api/products" }, { method: "GET", path: "/api/products/:id" }, { method: "PUT", path: "/api/products/:id" }, { method: "DELETE", path: "/api/products/:id" }] }] },
  },
  {
    name: "TicketSystem", label: "工单系统",
    prd: { projectName: "TicketSystem", domain: "enterprise", summary: "工单管理", features: [{ name: "工单管理", priority: "P0" }], pages: [{ name: "首页", route: "/home" }], personas: [], userStories: [] },
    arch: { databaseSchema: [{ table: "tickets", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "owner_id", type: "TEXT", constraints: "NOT NULL, FK → users.id" }, { name: "title", type: "TEXT", constraints: "NOT NULL" }, { name: "description", type: "TEXT", constraints: "NOT NULL" }, { name: "priority", type: "TEXT" }, { name: "status", type: "TEXT" }, { name: "assignee_id", type: "TEXT" }, { name: "created_at", type: "TEXT" }] }, { table: "comments", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "ticket_id", type: "TEXT", constraints: "NOT NULL, FK → tickets.id" }, { name: "user_id", type: "TEXT", constraints: "NOT NULL" }, { name: "content", type: "TEXT", constraints: "NOT NULL" }, { name: "created_at", type: "TEXT" }] }], apiDesign: [{ resource: "tickets", basePath: "/api/tickets", endpoints: [{ method: "GET", path: "/api/tickets" }, { method: "POST", path: "/api/tickets" }, { method: "GET", path: "/api/tickets/:id" }, { method: "PUT", path: "/api/tickets/:id" }, { method: "DELETE", path: "/api/tickets/:id" }] }] },
  },
  {
    name: "BlogCMS", label: "博客CMS",
    prd: { projectName: "BlogCMS", domain: "note", summary: "博客系统", features: [{ name: "文章管理", priority: "P0" }], pages: [{ name: "首页", route: "/home" }], personas: [], userStories: [] },
    arch: { databaseSchema: [{ table: "posts", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "author_id", type: "TEXT", constraints: "NOT NULL, FK → users.id" }, { name: "title", type: "TEXT", constraints: "NOT NULL" }, { name: "content", type: "TEXT", constraints: "NOT NULL" }, { name: "slug", type: "TEXT" }, { name: "status", type: "TEXT" }, { name: "created_at", type: "TEXT" }, { name: "updated_at", type: "TEXT" }] }, { table: "tags", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "name", type: "TEXT", constraints: "UNIQUE NOT NULL" }, { name: "created_at", type: "TEXT" }] }, { table: "post_tags", fields: [{ name: "post_id", type: "TEXT", constraints: "NOT NULL, FK → posts.id" }, { name: "tag_id", type: "TEXT", constraints: "NOT NULL, FK → tags.id" }] }], apiDesign: [{ resource: "posts", basePath: "/api/posts", endpoints: [{ method: "GET", path: "/api/posts" }, { method: "POST", path: "/api/posts" }, { method: "GET", path: "/api/posts/:id" }, { method: "PUT", path: "/api/posts/:id" }, { method: "DELETE", path: "/api/posts/:id" }] }] },
  },
  {
    name: "ProjectMgmt", label: "项目管理",
    prd: { projectName: "ProjectMgmt", domain: "enterprise", summary: "项目管理", features: [{ name: "项目管理", priority: "P0" }], pages: [{ name: "首页", route: "/home" }], personas: [], userStories: [] },
    arch: { databaseSchema: [{ table: "projects", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "owner_id", type: "TEXT", constraints: "NOT NULL, FK → users.id" }, { name: "name", type: "TEXT", constraints: "NOT NULL" }, { name: "description", type: "TEXT" }, { name: "status", type: "TEXT" }, { name: "created_at", type: "TEXT" }] }, { table: "tasks", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "project_id", type: "TEXT", constraints: "NOT NULL, FK → projects.id" }, { name: "title", type: "TEXT", constraints: "NOT NULL" }, { name: "assignee_id", type: "TEXT" }, { name: "status", type: "TEXT" }, { name: "priority", type: "TEXT" }, { name: "created_at", type: "TEXT" }] }], apiDesign: [{ resource: "projects", basePath: "/api/projects", endpoints: [{ method: "GET", path: "/api/projects" }, { method: "POST", path: "/api/projects" }, { method: "GET", path: "/api/projects/:id" }, { method: "PUT", path: "/api/projects/:id" }, { method: "DELETE", path: "/api/projects/:id" }] }] },
  },
  {
    name: "HRSystem", label: "人力资源",
    prd: { projectName: "HRSystem", domain: "enterprise", summary: "人力资源管理", features: [{ name: "员工管理", priority: "P0" }], pages: [{ name: "首页", route: "/home" }], personas: [], userStories: [] },
    arch: { databaseSchema: [{ table: "employees", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "user_id", type: "TEXT", constraints: "NOT NULL, FK → users.id" }, { name: "name", type: "TEXT", constraints: "NOT NULL" }, { name: "department", type: "TEXT", constraints: "NOT NULL" }, { name: "position", type: "TEXT", constraints: "NOT NULL" }, { name: "hire_date", type: "TEXT" }, { name: "created_at", type: "TEXT" }] }, { table: "attendances", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "employee_id", type: "TEXT", constraints: "NOT NULL, FK → employees.id" }, { name: "check_in", type: "TEXT" }, { name: "check_out", type: "TEXT" }, { name: "date", type: "TEXT", constraints: "NOT NULL" }, { name: "status", type: "TEXT" }] }, { table: "leaves", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "employee_id", type: "TEXT", constraints: "NOT NULL, FK → employees.id" }, { name: "type", type: "TEXT", constraints: "NOT NULL" }, { name: "start_date", type: "TEXT", constraints: "NOT NULL" }, { name: "end_date", type: "TEXT", constraints: "NOT NULL" }, { name: "status", type: "TEXT" }, { name: "reason", type: "TEXT" }, { name: "created_at", type: "TEXT" }] }], apiDesign: [{ resource: "employees", basePath: "/api/employees", endpoints: [{ method: "GET", path: "/api/employees" }, { method: "POST", path: "/api/employees" }, { method: "GET", path: "/api/employees/:id" }, { method: "PUT", path: "/api/employees/:id" }, { method: "DELETE", path: "/api/employees/:id" }] }] },
  },
  {
    name: "AssetMgmt", label: "资产管理",
    prd: { projectName: "AssetMgmt", domain: "enterprise", summary: "资产管理", features: [{ name: "资产管理", priority: "P0" }], pages: [{ name: "首页", route: "/home" }], personas: [], userStories: [] },
    arch: { databaseSchema: [{ table: "assets", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "owner_id", type: "TEXT", constraints: "NOT NULL, FK → users.id" }, { name: "name", type: "TEXT", constraints: "NOT NULL" }, { name: "category", type: "TEXT", constraints: "NOT NULL" }, { name: "serial_number", type: "TEXT" }, { name: "status", type: "TEXT" }, { name: "assigned_to", type: "TEXT" }, { name: "purchase_date", type: "TEXT" }, { name: "created_at", type: "TEXT" }] }, { table: "assignments", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "asset_id", type: "TEXT", constraints: "NOT NULL, FK → assets.id" }, { name: "user_id", type: "TEXT", constraints: "NOT NULL" }, { name: "assigned_at", type: "TEXT" }, { name: "returned_at", type: "TEXT" }, { name: "note", type: "TEXT" }] }], apiDesign: [{ resource: "assets", basePath: "/api/assets", endpoints: [{ method: "GET", path: "/api/assets" }, { method: "POST", path: "/api/assets" }, { method: "GET", path: "/api/assets/:id" }, { method: "PUT", path: "/api/assets/:id" }, { method: "DELETE", path: "/api/assets/:id" }] }] },
  },
  {
    name: "CourseMgmt", label: "课程管理",
    prd: { projectName: "CourseMgmt", domain: "education", summary: "课程管理", features: [{ name: "课程管理", priority: "P0" }], pages: [{ name: "首页", route: "/home" }], personas: [], userStories: [] },
    arch: { databaseSchema: [{ table: "courses", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "instructor_id", type: "TEXT", constraints: "NOT NULL, FK → users.id" }, { name: "title", type: "TEXT", constraints: "NOT NULL" }, { name: "description", type: "TEXT" }, { name: "price", type: "REAL" }, { name: "status", type: "TEXT" }, { name: "created_at", type: "TEXT" }] }, { table: "lessons", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "course_id", type: "TEXT", constraints: "NOT NULL, FK → courses.id" }, { name: "title", type: "TEXT", constraints: "NOT NULL" }, { name: "content", type: "TEXT" }, { name: "sort_order", type: "INTEGER" }, { name: "created_at", type: "TEXT" }] }, { table: "enrollments", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "course_id", type: "TEXT", constraints: "NOT NULL, FK → courses.id" }, { name: "user_id", type: "TEXT", constraints: "NOT NULL" }, { name: "enrolled_at", type: "TEXT" }, { name: "progress", type: "INTEGER" }] }], apiDesign: [{ resource: "courses", basePath: "/api/courses", endpoints: [{ method: "GET", path: "/api/courses" }, { method: "POST", path: "/api/courses" }, { method: "GET", path: "/api/courses/:id" }, { method: "PUT", path: "/api/courses/:id" }, { method: "DELETE", path: "/api/courses/:id" }] }] },
  },
  {
    name: "AppointmentScheduling", label: "预约排程",
    prd: { projectName: "Appointment", domain: "enterprise", summary: "预约管理", features: [{ name: "预约管理", priority: "P0" }], pages: [{ name: "首页", route: "/home" }], personas: [], userStories: [] },
    arch: { databaseSchema: [{ table: "appointments", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "user_id", type: "TEXT", constraints: "NOT NULL, FK → users.id" }, { name: "provider_id", type: "TEXT" }, { name: "service", type: "TEXT", constraints: "NOT NULL" }, { name: "scheduled_at", type: "TEXT", constraints: "NOT NULL" }, { name: "duration_min", type: "INTEGER" }, { name: "status", type: "TEXT" }, { name: "notes", type: "TEXT" }, { name: "created_at", type: "TEXT" }] }, { table: "availability", fields: [{ name: "id", type: "TEXT", constraints: "PK" }, { name: "provider_id", type: "TEXT", constraints: "NOT NULL" }, { name: "day_of_week", type: "INTEGER", constraints: "NOT NULL" }, { name: "start_time", type: "TEXT", constraints: "NOT NULL" }, { name: "end_time", type: "TEXT", constraints: "NOT NULL" }] }], apiDesign: [{ resource: "appointments", basePath: "/api/appointments", endpoints: [{ method: "GET", path: "/api/appointments" }, { method: "POST", path: "/api/appointments" }, { method: "GET", path: "/api/appointments/:id" }, { method: "PUT", path: "/api/appointments/:id" }, { method: "DELETE", path: "/api/appointments/:id" }] }] },
  },
];

// --- HTTP helpers ---
function httpPost(url, body, token) {
  return new Promise((resolve, reject) => {
    const payload = JSON.stringify(body);
    const u = new URL(url);
    const headers = { "Content-Type": "application/json", "Content-Length": payload.length.toString() };
    if (token) headers["Authorization"] = `Bearer ${token}`;
    const req = http.request({ hostname: u.hostname, port: u.port, path: u.pathname, method: "POST", headers, timeout: 10000 }, (res) => {
      let d = ""; res.on("data", c => d += c); res.on("end", () => { try { resolve(JSON.parse(d)); } catch { resolve({ raw: d, status: res.statusCode }); } });
    });
    req.on("error", reject);
    req.write(payload);
    req.end();
  });
}

function httpGet(url, token) {
  return new Promise((resolve, reject) => {
    const u = new URL(url);
    const headers = {};
    if (token) headers["Authorization"] = `Bearer ${token}`;
    http.get({ hostname: u.hostname, port: u.port, path: u.pathname, headers, timeout: 10000 }, (res) => {
      let d = ""; res.on("data", c => d += c); res.on("end", () => { try { resolve(JSON.parse(d)); } catch { resolve({ raw: d, status: res.statusCode }); } });
    }).on("error", reject);
  });
}

function httpPut(url, body, token) {
  return new Promise((resolve, reject) => {
    const payload = JSON.stringify(body);
    const u = new URL(url);
    const headers = { "Content-Type": "application/json", "Content-Length": payload.length.toString() };
    if (token) headers["Authorization"] = `Bearer ${token}`;
    const req = http.request({ hostname: u.hostname, port: u.port, path: u.pathname, method: "PUT", headers, timeout: 10000 }, (res) => {
      let d = ""; res.on("data", c => d += c); res.on("end", () => { try { resolve(JSON.parse(d)); } catch { resolve({ raw: d, status: res.statusCode }); } });
    });
    req.on("error", reject);
    req.write(payload);
    req.end();
  });
}

function waitForServer(url, timeoutMs = 20000) {
  return new Promise((resolve, reject) => {
    const start = Date.now();
    function check() {
      http.get(url, (res) => { res.resume(); res.on("end", resolve); }).on("error", () => {
        if (Date.now() - start > timeoutMs) reject(new Error("Server never started"));
        else setTimeout(check, 500);
      });
    }
    check();
  });
}

async function runCustomCommand(domainLabel, tmpDir, installOnly = false) {
  try {
    execSync("npm install --no-audit --no-fund", { cwd: tmpDir, encoding: "utf-8", timeout: 180000, stdio: "pipe" });
    return true;
  } catch {
    return false;
  }
}

async function runDomain(i, domain) {
  console.log(`\n${"─".repeat(60)}`);
  console.log(`[${i + 1}/${DOMAINS.length}] ${domain.label} (${domain.name})`);
  console.log(`${"─".repeat(60)}`);

  const result = {
    name: domain.name,
    label: domain.label,
    files: 0,
    build: false,
    health: false,
    register: false,
    login: false,
    create: false,
    read: false,
    update: false,
    delete: false,
    errors: [],
    timeMs: 0,
  };
  const t0 = Date.now();

  const tmpDir = `${BENCH_DIR}/${domain.name}`;
  rmSync(tmpDir, { recursive: true, force: true });

  // 1. Generate
  try {
    const { composeFullstack, writeFullstack } = await import("../../scripts/fullstack-composer-agent.mjs");
    const genResult = await composeFullstack(domain.prd, domain.arch);
    if (genResult.error) {
      result.errors.push(`Generation: ${genResult.error} ${genResult.message}`);
      result.timeMs = Date.now() - t0;
      return result;
    }
    writeFullstack(genResult, tmpDir);
    result.files = genResult.stats.totalFiles;
    console.log(`  Generated ${result.files} files`);
  } catch (e) {
    result.errors.push(`Generation: ${e.message}`);
    result.timeMs = Date.now() - t0;
    return result;
  }

  // Clean stale db
  try { rmSync(tmpDir + "/apps/api/data", { recursive: true, force: true }); } catch {}

  // 2. Install
  console.log("  npm install...");
  try {
    execSync("npm install --no-audit --no-fund", { cwd: tmpDir, encoding: "utf-8", timeout: 180000, stdio: "pipe" });
    console.log("  ✅ npm install");
  } catch (e) {
    result.errors.push(`npm install: ${(e.stderr || "").slice(0, 200)}`);
    console.log("  ❌ npm install failed");
    result.timeMs = Date.now() - t0;
    return result;
  }

  // 3. Build (tsc)
  console.log("  tsc...");
  try {
    execSync("npx tsc --noEmit", { cwd: tmpDir + "/apps/api", encoding: "utf-8", timeout: 60000, stdio: "pipe" });
    result.build = true;
    console.log("  ✅ tsc");
  } catch (e) {
    result.errors.push(`tsc: ${(e.stdout || e.stderr || "").slice(0, 200)}`);
    console.log("  ❌ tsc failed");
    result.timeMs = Date.now() - t0;
    return result;
  }

  // 4. Server + API
  const port = 4100 + i;
  const proc = spawn("npx", ["tsx", "src/index.ts"], {
    cwd: tmpDir + "/apps/api",
    env: { ...process.env, JWT_SECRET: `bench-${i}`, DATABASE_URL: ":memory:", PORT: String(port) },
    stdio: "pipe",
  });

  try {
    await waitForServer(`http://localhost:${port}/api/health`);
    console.log("  ✅ Server started");
  } catch (e) {
    result.errors.push(`Server start: ${e.message}`);
    console.log("  ❌ Server failed to start");
    proc.kill("SIGTERM");
    result.timeMs = Date.now() - t0;
    return result;
  }
  result.health = true;

  // Auth
  const username = `u${Date.now()}`;
  try {
    const reg = await httpPost(`http://localhost:${port}/api/auth/register`, { username, password: "123456" });
    if (!reg.token || !reg.user?.id) throw new Error(`malformed: ${JSON.stringify(reg).slice(0, 100)}`);
    const token = reg.token;
    const userId = reg.user.id;
    result.register = true;
    console.log("  ✅ Register");

    // Login
    try {
      const login = await httpPost(`http://localhost:${port}/api/auth/login`, { username, password: "123456" });
      if (login.token) result.login = true;
      console.log("  ✅ Login");
    } catch (e) {
      result.errors.push(`Login: ${e.message}`);
      console.log("  ❌ Login");
    }

    // CRUD — find resource endpoint with POST
    const resource = (domain.arch.apiDesign || [])[0];
    const crudPath = resource?.basePath || "";
    const base = `http://localhost:${port}${crudPath}`;

    // Build create payload: FK→userId, required fields→sample
    const table = (domain.arch.databaseSchema || [])[0];
    const payload = {};
    for (const f of (table?.fields || [])) {
      if (f.name === "id") continue;
      const fname = f.name.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
      if (f.constraints?.includes("FK")) {
        payload[fname] = userId;
      } else if (f.constraints?.includes("NOT NULL")) {
        if (f.type?.toUpperCase().includes("INT") || f.type?.toUpperCase().includes("REAL")) payload[fname] = 42;
        else if (f.type?.toUpperCase().includes("TEXT")) payload[fname] = `bench-${domain.name}`;
      }
    }

    // Create
    let createdId;
    try {
      const create = await httpPost(base, payload, token);
      createdId = create.data?.id;
      if (createdId) {
        result.create = true;
        console.log("  ✅ Create");
      } else {
        result.errors.push(`Create: no id in ${JSON.stringify(create).slice(0, 200)}`);
        console.log("  ❌ Create: no id");
      }
    } catch (e) {
      result.errors.push(`Create: ${e.message}`);
      console.log("  ❌ Create");
    }

    // Read
    if (createdId) {
      try {
        const list = await httpGet(base, token);
        if (list.data?.length > 0) result.read = true;
        console.log(`  ${result.read ? "✅" : "❌"} Read`);
      } catch (e) {
        result.errors.push(`Read: ${e.message}`);
        console.log("  ❌ Read");
      }

      // Update
      try {
        const upd = await httpPut(`${base}/${createdId}`, { ...payload }, token);
        if (upd.data?.id) result.update = true;
        console.log(`  ${result.update ? "✅" : "❌"} Update`);

        // Delete
        try {
          const del = await httpRequest("DELETE", `${base}/${createdId}`, null, token);
          if (del >= 200 && del < 300) result.delete = true;
          console.log(`  ${result.delete ? "✅" : "❌"} Delete (HTTP ${del})`);
        } catch (e) {
          result.errors.push(`Delete: ${e.message}`);
          console.log("  ❌ Delete");
        }
      } catch (e) {
        // PUT failed but try DELETE anyway with POST (some frameworks lack PUT)
        try {
          const del = await httpRequest("DELETE", `${base}/${createdId}`, null, token);
          if (del >= 200 && del < 300) result.delete = true;
          console.log(`  ${result.delete ? "✅" : "❌"} Delete (HTTP ${del})`);
        } catch (e2) {
          result.errors.push(`Update/Delete: ${e.message}; ${e2.message}`);
        }
      }
    }

  } catch (e) {
    result.errors.push(`Auth: ${e.message}`);
    console.log("  ❌ Auth failed");
  }

  proc.kill("SIGTERM");
  result.timeMs = Date.now() - t0;
  return result;
}

function httpRequest(method, url, body, token) {
  return new Promise((resolve, reject) => {
    const u = new URL(url);
    const headers = {};
    if (body) {
      const p = JSON.stringify(body);
      headers["Content-Type"] = "application/json";
      headers["Content-Length"] = p.length.toString();
    }
    if (token) headers["Authorization"] = `Bearer ${token}`;
    const req = http.request({ hostname: u.hostname, port: u.port, path: u.pathname, method, headers, timeout: 10000 }, (res) => {
      let d = ""; res.on("data", c => d += c); res.on("end", () => resolve(res.statusCode));
    });
    req.on("error", reject);
    if (body) req.write(JSON.stringify(body));
    req.end();
  });
}

// --- Report ---
function generateReport(results, totalMs) {
  const pass = r => r.build && r.create && r.read && r.update && r.delete;
  const passed = results.filter(pass);
  const lines = [];

  lines.push("# SF-05 Domain Benchmark Report");
  lines.push("");
  lines.push(`> **Generated:** ${new Date().toISOString()}`);
  lines.push(`> **Domains Tested:** ${results.length}`);
  lines.push(`> **Total Time:** ${(totalMs / 1000).toFixed(1)}s`);
  lines.push("");

  lines.push("## Summary");
  lines.push("");
  lines.push(`| Metric | Value |`);
  lines.push(`|--------|-------|`);
  lines.push(`| Total Domains | ${results.length} |`);
  lines.push(`| Build Pass | ${results.filter(r => r.build).length}/${results.length} |`);
  lines.push(`| CRUD Pass | ${passed.length}/${results.length} |`);
  lines.push(`| PASS RATE | **${((passed.length / results.length) * 100).toFixed(0)}%** |`);
  lines.push(`| Avg Files | ${(results.reduce((s, r) => s + r.files, 0) / results.length).toFixed(0)} |`);
  lines.push("");

  lines.push("## Domain Results");
  lines.push("");
  lines.push(`| # | Domain | Files | Build | Health | Register | Login | Create | Read | Update | Delete | Result |`);
  lines.push(`|---|--------|-------|-------|--------|----------|-------|--------|------|--------|--------|--------|`);
  for (let i = 0; i < results.length; i++) {
    const r = results[i];
    const ik = v => v ? "✅" : "❌";
    const status = pass(r) ? "✅ PASS" : r.build ? "⚠️ PARTIAL" : "❌ FAIL";
    lines.push(`| ${i + 1} | ${r.name} | ${r.files} | ${ik(r.build)} | ${ik(r.health)} | ${ik(r.register)} | ${ik(r.login)} | ${ik(r.create)} | ${ik(r.read)} | ${ik(r.update)} | ${ik(r.delete)} | ${status} |`);
  }
  lines.push("");

  // Failures
  const failed = results.filter(r => !pass(r));
  if (failed.length > 0) {
    lines.push("## Failure Analysis");
    lines.push("");
    for (const r of failed) {
      lines.push(`### ${r.name} (${r.label})`);
      for (const e of r.errors) lines.push(`- ${e}`);
      lines.push("");
    }
  }

  lines.push("## ✅ Passed");
  if (passed.length > 0) {
    for (const r of passed) lines.push(`- **${r.name}** (${r.label}) — ${r.files} files, ${(r.timeMs / 1000).toFixed(1)}s`);
  } else {
    lines.push("None — all domains have issues.");
  }
  lines.push("");

  lines.push("## Required Fixes");
  const errorCats = {};
  for (const r of failed) for (const e of r.errors) {
    const cat = e.split(":")[0];
    errorCats[cat] = (errorCats[cat] || 0) + 1;
  }
  for (const [cat, count] of Object.entries(errorCats).sort((a, b) => b[1] - a[1])) {
    lines.push(`- **${cat}**: ${count} occurrence(s)`);
  }

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

// --- Main ---
async function main() {
  console.log("=".repeat(60));
  console.log("SF-05 Domain Benchmark Suite");
  console.log("=".repeat(60));

  const t0 = Date.now();
  const results = [];

  // Clear temp
  rmSync(BENCH_DIR, { recursive: true, force: true });

  for (let i = 0; i < DOMAINS.length; i++) {
    const r = await runDomain(i, DOMAINS[i]);
    results.push(r);
  }

  const elapsed = Date.now() - t0;
  const report = generateReport(results, elapsed);
  writeFileSync(resolve(WORKSPACE, "benchmark-report.md"), report);

  console.log(`\n${"=".repeat(60)}`);
  console.log(`📊 Report: benchmark-report.md`);
  console.log(`${"=".repeat(60)}`);
  console.log(report);
}

main().catch(err => { console.error("FAIL:", err); process.exit(1); });
