#!/usr/bin/env node
/**
 * Quick single-domain end-to-end smoke test
 * Usage: node test/benchmark/smoke-one.mjs
 */

import { execSync, spawn } from "node:child_process";
import { existsSync, rmSync, mkdirSync } from "node:fs";
import * as http from "node:http";

const TMP = "/tmp/smoke-test";

async function main() {
  console.log("=== Smoke Test: PetCare end-to-end ===\n");
  rmSync(TMP, { recursive: true, force: true });

  // 1. Generate
  console.log("1. Generate fullstack...");
  const { composeFullstack, writeFullstack } = await import("../../scripts/fullstack-composer-agent.mjs");
  const prd = { projectName: "PetCare", domain: "pet", summary: "宠物管理", features: [], pages: [{ name: "首页", route: "/home" }], personas: [], userStories: [] };
  const 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: "created_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" }
    ]}]
  };
  const result = await composeFullstack(prd, arch);
  writeFullstack(result, TMP);
  console.log(`   ✅ ${result.stats.totalFiles} files`);

  // 2. Install
  console.log("2. npm install...");
  execSync("npm install --no-audit --no-fund", { cwd: TMP, encoding: "utf-8", timeout: 120000, stdio: "pipe" });
  // Also rm any stale db
  try { rmSync(TMP + "/apps/api/data", { recursive: true, force: true }); } catch {}
  console.log("   ✅");

  // 3. Build
  console.log("3. tsc --noEmit...");
  execSync("npx tsc --noEmit", { cwd: TMP + "/apps/api", encoding: "utf-8", timeout: 60000, stdio: "pipe" });
  console.log("   ✅");

  // 4. Start server
  console.log("4. Start server...");
  const proc = spawn("npx", ["tsx", "src/index.ts"], {
    cwd: TMP + "/apps/api",
    env: { ...process.env, JWT_SECRET: "test", DATABASE_URL: ":memory:", PORT: "5678" },
    stdio: "pipe",
  });
  await waitFor("http://localhost:5678/api/health", 15000);
  console.log("   ✅");

  // 5. Auth
  console.log("5. Register...");
  const regResult = await postJson("http://localhost:5678/api/auth/register", { username: `u_${Date.now()}`, password: "123456" });
  const token = regResult.token;
  const userId = regResult.user?.id;
  if (!token || !userId) throw new Error(`Register failed: ${JSON.stringify(regResult)}`);
  console.log(`   ✅ user=${userId.slice(0, 12)}`);

  console.log("6. Login...");
  const { token: token2 } = await postJson("http://localhost:5678/api/auth/login", { username: "u1", password: "123456" });
  const authToken = token2 || token;
  console.log(`   ✅`);

  // 6. CRUD
  console.log("7. Create pet...");
  const { data: pet } = await postJson("http://localhost:5678/api/pets", { name: "毛球", species: "猫", ownerId: userId }, authToken);
  console.log(`   ✅ ${pet.id.slice(0, 12)}`);

  console.log("8. List pets...");
  const list = await getJson("http://localhost:5678/api/pets", authToken);
  console.log(`   ✅ ${list.data.length} pet(s)`);

  console.log("9. Update pet...");
  await putJson(`http://localhost:5678/api/pets/${pet.id}`, { species: "狗" }, authToken);
  console.log("   ✅");

  console.log("10. Delete pet...");
  const delCode = await deleteReq(`http://localhost:5678/api/pets/${pet.id}`, authToken);
  console.log(`   ✅ HTTP ${delCode}`);

  proc.kill("SIGTERM");

  console.log("\n🎉 ALL SMOKE TESTS PASSED");
}

// --- HTTP helpers ---
function waitFor(url, timeout) {
  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 > timeout) reject(new Error("Server never started"));
        else setTimeout(check, 500);
      });
    }
    check();
  });
}

function httpReq({ url, method, body, token }) {
  return new Promise((resolve, reject) => {
    const u = new URL(url);
    const payload = body ? JSON.stringify(body) : undefined;
    const headers = { "Content-Type": "application/json" };
    if (payload) headers["Content-Length"] = Buffer.byteLength(payload);
    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({ status: res.statusCode, body: d }));
    });
    req.on("error", reject);
    if (payload) req.write(payload);
    req.end();
  });
}

async function postJson(url, body, token) {
  const { body: b } = await httpReq({ url, method: "POST", body, token });
  return JSON.parse(b);
}
async function getJson(url, token) {
  const { body: b } = await httpReq({ url, method: "GET", token });
  return JSON.parse(b);
}
async function putJson(url, body, token) {
  const { body: b } = await httpReq({ url, method: "PUT", body, token });
  return JSON.parse(b);
}
async function deleteReq(url, token) {
  const { status } = await httpReq({ url, method: "DELETE", token });
  return status;
}

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