/**
 * cmd-init.js — `qa-stlc init`
 *
 * Full bootstrap: install Python agents + skills + ORCHESTRATION_RULES.md + MCP config.
 * Accepts --integration <ado|jira|both>.  When omitted, reads
 * ~/.qa-stlc/integration (written by postinstall) or prompts interactively.
 */
"use strict";

const { execSync, spawnSync } = require("child_process");
const path = require("path");
const fs   = require("fs");
const os   = require("os");

const cmdSkills       = require("./cmd-skills");
const cmdMcpConfig    = require("./cmd-mcp-config");
const {
  checkFrameworkUpgradeCompatibility,
  detectFrameworkDrift,
  formatCompatibilityIssues,
} = require("./framework-upgrade-support");
const pickIntegration = require("./prompt-integration");

const PREF_FILE = path.join(os.homedir(), ".qa-stlc", "integration");

function readSavedIntegration() {
  try {
    if (fs.existsSync(PREF_FILE)) return fs.readFileSync(PREF_FILE, "utf8").trim();
  } catch (_) {}
  return null;
}

function saveIntegration(value) {
  try {
    fs.mkdirSync(path.dirname(PREF_FILE), { recursive: true });
    fs.writeFileSync(PREF_FILE, value, "utf8");
  } catch (_) {}
}

const C = {
  reset: "\x1b[0m", bold: "\x1b[1m",
  green: "\x1b[32m", cyan: "\x1b[36m",
  yellow: "\x1b[33m", red: "\x1b[31m", dim: "\x1b[2m",
};
const ok   = (m) => console.log(`${C.green}✓${C.reset}  ${m}`);
const info = (m) => console.log(`${C.cyan}→${C.reset}  ${m}`);
const warn = (m) => console.log(`${C.yellow}⚠${C.reset}  ${m}`);
const die  = (m) => { console.error(`${C.red}✗${C.reset}  ${m}`); process.exit(1); };

module.exports = async function init(opts) {
  console.log(`\n${C.bold}QA STLC Agents — init${C.reset}\n`);

  // ── 1. Check Python ──────────────────────────────────────────────────────
  const python = opts.python || "python3";
  info(`Checking Python (${python})…`);
  const pyCheck = spawnSync(python, ["--version"], { encoding: "utf8" });
  if (pyCheck.status !== 0) {
    die(`Python not found at '${python}'. Install Python 3.10+ or pass --python <path>.`);
  }
  const pyVersion = (pyCheck.stdout || pyCheck.stderr || "").trim();
  const match = pyVersion.match(/Python (\d+)\.(\d+)/);
  if (!match || parseInt(match[1]) < 3 || parseInt(match[2]) < 10) {
    die(`Python 3.10+ required, found: ${pyVersion}`);
  }
  ok(`${pyVersion} found.`);

  // ── 2. Resolve integration choice ────────────────────────────────────────
  // Priority: --integration flag > saved preference > interactive prompt
  let integration = (opts.integration || "").toLowerCase().trim();
  const validIntegrations = ["ado", "jira", "both"];
  if (integration && !validIntegrations.includes(integration)) {
    die(`Invalid --integration value: "${integration}". Use ado, jira, or both.`);
  }
  if (!integration) {
    integration = readSavedIntegration();
  }
  if (!integration) {
    integration = await pickIntegration("ado");
  }
  saveIntegration(integration);

  const needsAdo  = integration === "ado"  || integration === "both";
  const needsJira = integration === "jira" || integration === "both";
  info(`Integration: ${C.bold}${integration}${C.reset}`);

  // ── 3. pip install qa-gentic-stlc-agents ──────────────────────────────────
  info("Installing qa-gentic-stlc-agents (pip)…");

  const IS_WIN   = process.platform === "win32";
  const VENV_DIR = path.join(os.homedir(), ".qa-stlc", "venv");
  const venvPython = IS_WIN
    ? path.join(VENV_DIR, "Scripts", "python.exe")
    : path.join(VENV_DIR, "bin", "python3");

  // Helper: check if the package is importable by a given python binary
  function isImportable(pyBin) {
    if (!fs.existsSync(pyBin) && pyBin !== python) return false;
    const r = spawnSync(pyBin, ["-c", "import qa_gentic_stlc_agents"], { encoding: "utf8" });
    return r.status === 0;
  }

  // Helper: return the installed package version for a given python, or null
  function installedVersion(pyBin) {
    const r = spawnSync(
      pyBin,
      ["-c", "import importlib.metadata as m; print(m.version('qa-gentic-stlc-agents'))"],
      { encoding: "utf8" }
    );
    return r.status === 0 ? (r.stdout || "").trim() : null;
  }

  // Helper: upgrade the package via the given python's pip. Quiet by default;
  // tolerates offline failure (so init still works without a network).
  function pipUpgrade(pyBin, label) {
    info(`Upgrading qa-gentic-stlc-agents in ${label}…`);
    const before = installedVersion(pyBin);
    const r = spawnSync(
      pyBin,
      ["-m", "pip", "install", "--upgrade", "--quiet", "qa-gentic-stlc-agents"],
      { stdio: ["ignore", "pipe", "pipe"], encoding: "utf8" }
    );
    const after = installedVersion(pyBin);
    if (r.status === 0) {
      if (before && after && before !== after) ok(`qa-gentic-stlc-agents ${before} → ${after}`);
      else if (after)                          ok(`qa-gentic-stlc-agents ${after} (already latest)`);
      else                                     ok("qa-gentic-stlc-agents upgrade complete");
    } else {
      warn(`Upgrade skipped (likely offline). Current: ${before || "unknown"}`);
    }
  }

  // Find a Python 3.10–3.13 binary compatible with qa-gentic-stlc-agents.
  // The package declares Requires-Python >=3.10,<3.14 so we must avoid 3.14+.
  function findCompatiblePython(preferred) {
    const candidates = IS_WIN
      ? ["py", "python", "python3"]
      : ["python3.13", "python3.12", "python3.11", "python3.10", preferred];

    for (const bin of candidates) {
      const r = spawnSync(bin, ["--version"], { encoding: "utf8" });
      if (r.status !== 0) continue;
      const ver = (r.stdout || r.stderr || "").trim();
      const m = ver.match(/Python (\d+)\.(\d+)/);
      if (!m) continue;
      const major = parseInt(m[1]), minor = parseInt(m[2]);
      if (major === 3 && minor >= 10 && minor <= 13) return bin;
    }
    return null;
  }

  // Determine which python to use for MCP servers — may be updated to venv python below
  let resolvedPython = python;

  if (isImportable(python)) {
    // Already importable by the user-supplied / system python (CI, active venv, etc.)
    ok(`qa-gentic-stlc-agents installed (${installedVersion(python) || "unknown"}).`);
    pipUpgrade(python, "system/user python");
  } else if (isImportable(venvPython)) {
    // Package found in the persistent qa-stlc venv from a previous run.
    // Always upgrade so projects scaffolded long ago aren't pinned to stale code.
    ok(`qa-gentic-stlc-agents found in ~/.qa-stlc/venv (${installedVersion(venvPython) || "unknown"}).`);
    pipUpgrade(venvPython, "~/.qa-stlc/venv");
    resolvedPython = venvPython;
  } else {
    // Create (or reuse) a dedicated venv and install there.
    // Bypasses PEP 668 on Mac/Linux Homebrew Python and works on Windows & CI
    // without requiring elevated permissions or breaking the system Python.

    // Find a Python 3.10–3.13 binary (package does not support 3.14+ yet)
    const compatPython = findCompatiblePython(python);
    if (!compatPython) {
      die(
        "qa-gentic-stlc-agents requires Python 3.10–3.13 but none was found.\n" +
        "  Mac:     brew install python@3.13\n" +
        "  Linux:   sudo apt install python3.13\n" +
        "  Windows: install Python 3.13 from python.org\n" +
        "  Then re-run: qa-stlc init --python python3.13 --vscode --integration ado"
      );
    }

    const compatPythonVer = (spawnSync(compatPython, ["--version"], { encoding: "utf8" }).stdout || "").trim();
    info(`Using ${compatPython} (${compatPythonVer}) for venv…`);

    if (!fs.existsSync(VENV_DIR)) {
      info(`Creating Python venv at ${VENV_DIR}…`);
      const mkVenv = spawnSync(compatPython, ["-m", "venv", VENV_DIR], { stdio: "inherit", encoding: "utf8" });
      if (mkVenv.status !== 0) {
        die(`Failed to create venv. Ensure python3-venv is installed:\n  ${compatPython} -m venv ${VENV_DIR}`);
      }
      ok("Venv created.");
    }

    info("Installing qa-gentic-stlc-agents into venv…");
    const pip = spawnSync(
      venvPython,
      ["-m", "pip", "install", "qa-gentic-stlc-agents>=1.0.1", "--quiet"],
      { stdio: "inherit", encoding: "utf8" }
    );

    if (pip.status !== 0) {
      die(`pip install into venv failed. Try manually:\n  ${venvPython} -m pip install qa-gentic-stlc-agents`);
    }
    ok("qa-gentic-stlc-agents installed into ~/.qa-stlc/venv.");
    resolvedPython = venvPython;
  }

  // Propagate the resolved python so MCP config points to the correct interpreter
  opts.python = resolvedPython;

  // ── 4. Copy ORCHESTRATION_RULES.md + migration-guide.md to project root ────
  info("Installing ORCHESTRATION_RULES.md to project root…");
  try {
    const npmPkgDir = path.join(path.dirname(require.resolve("@qa-gentic/stlc-agents/package.json")));
    const srcRules = path.join(npmPkgDir, "ORCHESTRATION_RULES.md");
    const destRules = path.join(process.cwd(), "ORCHESTRATION_RULES.md");
    if (fs.existsSync(srcRules)) {
      fs.copyFileSync(srcRules, destRules);
      ok("ORCHESTRATION_RULES.md copied to project root.");
    } else {
      warn("ORCHESTRATION_RULES.md not found in npm package (expected in development).");
    }

    const srcMigrationGuide = path.join(npmPkgDir, "docs", "migration-guide.md");
    const destMigrationGuide = path.join(process.cwd(), "migration-guide.md");
    if (fs.existsSync(srcMigrationGuide)) {
      fs.copyFileSync(srcMigrationGuide, destMigrationGuide);
      ok("migration-guide.md copied to project root.");
    } else {
      warn("docs/migration-guide.md not found in npm package (expected in development).");
    }
  } catch (e) {
    // Silently skip if not available (common in dev environments before full build)
  }

  // ── 5. Install skills ─────────────────────────────────────────────────────
  info("Installing skills…");
  const skillTarget = opts.vscode ? "vscode" : "claude";
  await cmdSkills({ target: skillTarget, integration });

  // ── 5. Write MCP config ───────────────────────────────────────────────────
  info("Writing MCP config…");
  await cmdMcpConfig({
    vscode:         opts.vscode || false,
    print:          false,
    python:         resolvedPython,
    playwrightPort: "8931",
    integration,
  });

  // ── 6. Advise on framework drift ─────────────────────────────────────────
  // qa-stlc init refreshes skills + MCP config + ORCHESTRATION_RULES, but it
  // intentionally does NOT touch src/utils/locators/* (those files are often
  // customized per project). A repo can therefore stay pinned to an old
  // framework with known bugs — e.g. the LocatorRepository upsert
  // short-circuit that drops every first-time heal — even after re-running
  // init against the latest agents build. Surface the drift so the user can
  // explicitly opt in to an upgrade.
  try {
    const driftReport = detectFrameworkDrift(process.cwd());
    if (driftReport && (driftReport.drift > 0 || driftReport.missing > 0)) {
      console.log("");
      const compatibility = checkFrameworkUpgradeCompatibility(process.cwd());
      if (compatibility.ok) {
        warn(
          `Self-healing framework files have drifted from the bundled version ` +
            `(${driftReport.drift} drifted, ${driftReport.missing} missing of ${driftReport.total}).`
        );
        console.log(
          `  ${C.dim}This is the file set that contains the heal store, the locator healer, and the timing/visual healers.${C.reset}\n` +
            `  ${C.dim}Bugs fixed upstream (e.g. heals not persisting) stay in your repo until you upgrade these files.${C.reset}\n` +
            `  ${C.cyan}qa-stlc upgrade-framework${C.reset}          ${C.dim}# dry-run — show which files would change${C.reset}\n` +
            `  ${C.cyan}qa-stlc upgrade-framework --apply${C.reset}  ${C.dim}# write the bundled versions (originals backed up to .bak.<ts>)${C.reset}`
        );
      } else {
        warn(
          `Framework files are missing, but this repo is not a full qa-stlc scaffold that can safely use qa-stlc upgrade-framework.`
        );
        console.log(
          `  ${C.dim}The bundled framework files assume support modules and tsconfig aliases that are not present here.${C.reset}`
        );
        console.log(`${formatCompatibilityIssues(compatibility)}`);
        console.log(
          `  ${C.cyan}stlc-migrate --source <existing-project> --helix <target>${C.reset}  ${C.dim}# migrate an existing Playwright suite into the full Helix-QA layout${C.reset}`
        );
      }
    }
  } catch (_) {
    // Non-fatal — drift detection is best-effort and never blocks init.
  }

  // ── 7. Done ───────────────────────────────────────────────────────────────
  const mcpLocation    = opts.vscode ? ".vscode/mcp.json" : ".mcp.json";
  const skillsLocation = opts.vscode
    ? ".github/copilot-instructions/  (reload VS Code window to activate)"
    : ".claude/skills/";

  const adoSection = needsAdo ? `
  ${C.dim}ADO pipeline:${C.reset}
  ${C.dim}1 →${C.reset} ${C.yellow}qa-test-case-manager${C.reset}     ${C.dim}ADO work item → manual test cases${C.reset}
  ${C.dim}2 →${C.reset} ${C.yellow}qa-gherkin-generator${C.reset}     ${C.dim}Epic / Feature / PBI → .feature file${C.reset}
  ${C.dim}3 →${C.reset} ${C.yellow}qa-playwright-generator${C.reset}  ${C.dim}Gherkin + live browser → self-healing Playwright${C.reset}
  ${C.dim}4 →${C.reset} ${C.yellow}qa-helix-writer${C.reset}          ${C.dim}Generated files → Helix-QA project${C.reset}` : "";

  const jiraSection = needsJira ? `
  ${C.dim}Jira pipeline:${C.reset}
  ${C.dim}1 →${C.reset} ${C.yellow}qa-jira-manager${C.reset}          ${C.dim}Fetch Jira issue + analyse acceptance criteria${C.reset}
  ${C.dim}2 →${C.reset} ${C.yellow}qa-jira-manager${C.reset}          ${C.dim}Generate test cases → create in Jira with 'is tested by' links${C.reset}
  ${C.dim}3 →${C.reset} ${C.yellow}qa-gherkin-generator${C.reset}     ${C.dim}Generate Gherkin .feature file from Jira issue AC${C.reset}
  ${C.dim}4 →${C.reset} ${C.yellow}qa-playwright-generator${C.reset}  ${C.dim}Gherkin + live browser → self-healing Playwright TypeScript${C.reset}
  ${C.dim}5 →${C.reset} ${C.yellow}qa-helix-writer${C.reset}          ${C.dim}Generated files → Helix-QA project on disk${C.reset}
  ${C.dim}   Requires: JIRA_CLIENT_ID + JIRA_CLIENT_SECRET + JIRA_CLOUD_ID in .env${C.reset}` : "";

  console.log(`
${C.bold}Setup complete.${C.reset}

  ${C.dim}Integration:${C.reset} ${C.bold}${integration}${C.reset}
  ${C.dim}MCP config :${C.reset} ${mcpLocation}
  ${C.dim}Skills     :${C.reset} ${skillsLocation}
  ${C.dim}Rules      :${C.reset} ORCHESTRATION_RULES.md ${C.dim}(project root — reference for multi-step workflows)${C.reset}
  ${C.dim}Migration  :${C.reset} migration-guide.md     ${C.dim}(project root — stlc-migrate reference for existing Playwright suites)${C.reset}

${C.bold}Start Playwright MCP${C.reset} ${C.dim}(keep running in a separate terminal):${C.reset}

  ${C.cyan}npx @playwright/mcp@latest --port 8931${C.reset}

${C.bold}STLC Workflow:${C.reset}
${adoSection}${jiraSection}

  ${C.dim}Shared:${C.reset}
  ${C.dim}+ →${C.reset} ${C.yellow}qa-migration${C.reset}             ${C.dim}One-shot migrate of an existing Playwright suite → Helix-QA layout${C.reset}
  ${C.dim}                              CLI: stlc-migrate --source <dir> --helix <dir>${C.reset}

${C.dim}Change integration at any time:  qa-stlc init --integration <ado|jira|both>${C.reset}
`);
};