const { spawn } = require("child_process");
const path = require("path");

function runGenerator(params, sseWriter, projectRoot) {
  const { sourceDir, sceneId, sceneName, sceneKind, targetUrl, outputRoot, lessons } = params;

  const normalize = (p) => p.replace(/\\/g, "/");

  const args = [
    "run",
    "--bin",
    "sg_scene_generate",
    "--",
    "--source-dir",
    normalize(sourceDir),
    "--scene-id",
    sceneId,
    "--scene-name",
    sceneName,
  ];

  // 只有明确指定 sceneKind 时才添加参数（否则使用默认值 report_collection）
  if (sceneKind) {
    args.push("--scene-kind", sceneKind);
  }

  // 如果提供了 targetUrl，添加参数
  if (targetUrl) {
    args.push("--target-url", targetUrl);
  }

  args.push("--output-root", normalize(outputRoot));

  if (lessons) {
    args.push("--lessons", normalize(lessons));
  }

  return new Promise((resolve, reject) => {
    sseWriter.write(
      `event: status\ndata: ${JSON.stringify({
        message: "开始生成 skill 包...",
      })}\n\n`
    );
    sseWriter.write(
      `event: status\ndata: ${JSON.stringify({
        message: `执行: cargo ${args.join(" ")}`,
      })}\n\n`
    );

    const child = spawn("cargo", args, {
      cwd: projectRoot,
      stdio: ["ignore", "pipe", "pipe"],
      env: { ...process.env, RUST_BACKTRACE: "1" },
    });

    let stdout = "";
    let stderr = "";
    let timedOut = false;

    const timeout = setTimeout(() => {
      timedOut = true;
      child.kill("SIGTERM");
      sseWriter.write(
        `event: error\ndata: ${JSON.stringify({
          message: "生成超时（5分钟）",
        })}\n\n`
      );
      resolve({ success: false, error: "timeout" });
    }, 5 * 60 * 1000);

    child.stdout.on("data", (data) => {
      const text = data.toString();
      stdout += text;
      sseWriter.write(
        `event: log\ndata: ${JSON.stringify({ message: text.trim() })}\n\n`
      );
    });

    child.stderr.on("data", (data) => {
      const text = data.toString();
      stderr += text;
      sseWriter.write(
        `event: log\ndata: ${JSON.stringify({ message: text.trim() })}\n\n`
      );
    });

    child.on("close", (code) => {
      clearTimeout(timeout);
      if (timedOut) return;

      if (code === 0) {
        const match = stdout.match(/generated scene package:\s*(.+)/);
        const skillRoot = match ? match[1] : null;
        sseWriter.write(
          `event: status\ndata: ${JSON.stringify({
            message: "✅ 生成成功",
          })}\n\n`
        );
        sseWriter.write(
          `event: complete\ndata: ${JSON.stringify({
            success: true,
            skillRoot,
          })}\n\n`
        );
        resolve({ success: true, skillRoot });
      } else {
        sseWriter.write(
          `event: error\ndata: ${JSON.stringify({
            message: `生成失败 (exit code ${code})`,
          })}\n\n`
        );
        if (stderr.trim()) {
          sseWriter.write(
            `event: error\ndata: ${JSON.stringify({
              message: stderr.substring(0, 500),
            })}\n\n`
          );
        }
        resolve({ success: false, code, stderr });
      }
    });

    child.on("error", (err) => {
      clearTimeout(timeout);
      sseWriter.write(
        `event: error\ndata: ${JSON.stringify({
          message: `无法启动 cargo: ${err.message}`,
        })}\n\n`
      );
      reject(err);
    });
  });
}

function readDirectory(sourceDir) {
  const fs = require("fs");
  const p = require("path");

  if (!fs.existsSync(sourceDir)) {
    throw new Error(`Directory not found: ${sourceDir}`);
  }

  const stat = fs.statSync(sourceDir);
  if (!stat.isDirectory()) {
    throw new Error(`Not a directory: ${sourceDir}`);
  }

  const result = {};
  const entries = fs.readdirSync(sourceDir, { withFileTypes: true });

  const treeLines = [];
  for (const entry of entries) {
    treeLines.push(`├── ${entry.name}`);
  }
  result.tree = treeLines.join("\n");

  const sceneTomlPath = p.join(sourceDir, "scene.toml");
  if (fs.existsSync(sceneTomlPath)) {
    result["scene.toml"] = fs.readFileSync(sceneTomlPath, "utf-8");
  }

  const skillTomlPath = p.join(sourceDir, "SKILL.toml");
  if (fs.existsSync(skillTomlPath)) {
    result["SKILL.toml"] = fs.readFileSync(skillTomlPath, "utf-8");
  }

  const skillMdPath = p.join(sourceDir, "SKILL.md");
  if (fs.existsSync(skillMdPath)) {
    result["SKILL.md"] = fs.readFileSync(skillMdPath, "utf-8");
  }

  // Read index.html
  const indexHtmlPath = p.join(sourceDir, "index.html");
  if (fs.existsSync(indexHtmlPath)) {
    result.indexHtml = fs.readFileSync(indexHtmlPath, "utf-8");
  }

  const scripts = {};
  for (const entry of entries) {
    if (entry.isFile() && entry.name.endsWith(".js")) {
      const scriptPath = p.join(sourceDir, entry.name);
      scripts[entry.name] = fs.readFileSync(scriptPath, "utf-8");
    }
  }
  if (Object.keys(scripts).length > 0) {
    result.scripts = scripts;
  }

  return result;
}

module.exports = { runGenerator, readDirectory };
