/**
 * cmd-skills.js — `qa-stlc skills`
 *
 * Copies skill markdown files into the correct directory for each coding agent:
 *
 *   claude    →  .claude/skills/  +  .claude/AGENT-BEHAVIOR.md
 *   vscode    →  .github/copilot-instructions/
 *   cursor    →  .cursor/rules/ (one file per skill)
 *   windsurf  →  .windsurf/rules/
 *   both      →  claude + vscode
 *   print     →  stdout only
 *
 * Also installs ORCHESTRATION_RULES.md to project root (multi-step workflow reference).
 */
"use strict";

const path = require("path");
const fs   = require("fs");

const C = {
  reset: "\x1b[0m", bold: "\x1b[1m",
  green: "\x1b[32m", yellow: "\x1b[33m", dim: "\x1b[2m",
};
const ok   = (m) => console.log(`${C.green}✓${C.reset}  ${m}`);
const info = (m) => console.log(`   ${C.dim}${m}${C.reset}`);
const warn = (m) => console.log(`${C.yellow}⚠${C.reset}  ${m}`);

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

function readIntegrationPrefSk() {
  try {
    if (fs.existsSync(PREF_FILE_SK))
      return fs.readFileSync(PREF_FILE_SK, "utf8").trim();
  } catch (_) {}
  return "ado";
}

// Resolve the skills bundled with this npm package
const PKG_ROOT           = path.resolve(__dirname, "../..");
const SKILLS_DIR         = path.join(PKG_ROOT, "skills");
const BEHAVIOR_MD        = path.join(SKILLS_DIR, "AGENT-BEHAVIOR.md");
const ORCHESTRATION_MD   = path.join(PKG_ROOT, "ORCHESTRATION_RULES.md");
const AGENTS_DIR         = path.join(PKG_ROOT, ".github", "agents");

/** Copy a file, creating parent dirs as needed. */
function cp(src, dest) {
  fs.mkdirSync(path.dirname(dest), { recursive: true });
  fs.copyFileSync(src, dest);
}

/**
 * List skill directories (each containing a SKILL.md), filtered by integration.
 * Returns objects: { name, skillMd, dir }
 */
function skillEntries(integration) {
  const integ = integration || readIntegrationPrefSk() || "ado";
  const includeJira = integ === "jira" || integ === "both";
  const adoOnlySkills = new Set(["generate-test-cases"]);
  return fs.readdirSync(SKILLS_DIR)
    .filter((entry) => {
      // Only directories with a SKILL.md
      const skillMd = path.join(SKILLS_DIR, entry, "SKILL.md");
      if (!fs.existsSync(skillMd)) return false;
      // Jira skill — only when integration includes jira
      if (entry === "qa-jira-manager" && !includeJira) return false;
      // ADO-only skills — exclude when integration is jira-only
      if (adoOnlySkills.has(entry) && integ === "jira") return false;
      return true;
    })
    .map((entry) => ({
      name: entry,
      skillMd: path.join(SKILLS_DIR, entry, "SKILL.md"),
      dir: path.join(SKILLS_DIR, entry),
    }));
}

/** Back-compat: returns array of SKILL.md paths (used for print/count). */
function skillFiles(integration) {
  return skillEntries(integration).map((e) => e.skillMd);
}

const CWD = process.cwd();

/** List .agent.md files, filtered by integration. */
function agentFiles(integration) {
  const integ = integration || readIntegrationPrefSk() || "ado";
  const includeJira = integ === "jira" || integ === "both";
  const adoOnlyAgents = new Set(["qa-test-case-manager.agent.md"]);
  return fs.readdirSync(AGENTS_DIR)
    .filter((f) => {
      if (!f.endsWith(".agent.md")) return false;
      if (f === "qa-jira-manager.agent.md" && !includeJira) return false;
      if (adoOnlyAgents.has(f) && integ === "jira") return false;
      return true;
    })
    .map((f) => path.join(AGENTS_DIR, f));
}

/** Install .agent.md files to .github/agents/ in the consumer project. */
function installAgents(integration) {
  if (!fs.existsSync(AGENTS_DIR)) return;
  const dest = path.join(CWD, ".github", "agents");
  for (const src of agentFiles(integration)) {
    cp(src, path.join(dest, path.basename(src)));
  }
  ok(`Agent files installed → .github/agents/`);
  agentFiles(integration).forEach((f) => info(path.basename(f)));
}

/** Install ORCHESTRATION_RULES.md to project root for multi-step workflow reference. */
function installOrchestrationRules() {
  if (!fs.existsSync(ORCHESTRATION_MD)) return;
  const dest = path.join(CWD, "ORCHESTRATION_RULES.md");
  cp(ORCHESTRATION_MD, dest);
  ok(`ORCHESTRATION_RULES.md installed → project root`);
  info("Reference this file for multi-step QA workflow best practices");
}

function installClaude(integration) {
  const dest = path.join(CWD, ".claude", "skills");
  // Copy entire skill directory (preserves references/ subdirectory)
  for (const entry of skillEntries(integration)) {
    const targetDir = path.join(dest, entry.name);
    fs.mkdirSync(targetDir, { recursive: true });
    copyDirRecursive(entry.dir, targetDir);
  }
  cp(BEHAVIOR_MD, path.join(CWD, ".claude", "AGENT-BEHAVIOR.md"));
  ok(`Skills installed → .claude/skills/`);
  info("AGENT-BEHAVIOR.md → .claude/AGENT-BEHAVIOR.md");
  skillEntries(integration).forEach((e) => info(`${e.name}/SKILL.md`));
  installAgents(integration);
  installOrchestrationRules();
  printPlaywrightHint();
}

function installVscode(integration) {
  const dest = path.join(CWD, ".github", "copilot-instructions");
  // Copy entire skill directory (preserves references/ subdirectory — same as Claude)
  for (const entry of skillEntries(integration)) {
    const targetDir = path.join(dest, entry.name);
    fs.mkdirSync(targetDir, { recursive: true });
    copyDirRecursive(entry.dir, targetDir);
  }
  cp(BEHAVIOR_MD, path.join(dest, "AGENT-BEHAVIOR.md"));
  ok(`Skills installed → .github/copilot-instructions/`);
  info("AGENT-BEHAVIOR.md → .github/copilot-instructions/AGENT-BEHAVIOR.md");
  skillEntries(integration).forEach((e) => info(`${e.name}/SKILL.md`));
  installAgents(integration);
  installOrchestrationRules();
  printPlaywrightHint();
}

function installCursor(integration) {
  const dest = path.join(CWD, ".cursor", "rules");
  // Flat copy: SKILL.md → <name>.md
  for (const entry of skillEntries(integration)) {
    cp(entry.skillMd, path.join(dest, `${entry.name}.md`));
  }
  cp(BEHAVIOR_MD, path.join(dest, "AGENT-BEHAVIOR.md"));
  ok(`Skills installed → .cursor/rules/`);
  installAgents(integration);
  installOrchestrationRules();
  printPlaywrightHint();
}

function installWindsurf(integration) {
  const dest = path.join(CWD, ".windsurf", "rules");
  // Flat copy: SKILL.md → <name>.md
  for (const entry of skillEntries(integration)) {
    cp(entry.skillMd, path.join(dest, `${entry.name}.md`));
  }
  cp(BEHAVIOR_MD, path.join(dest, "AGENT-BEHAVIOR.md"));
  ok(`Skills installed → .windsurf/rules/`);
  installAgents(integration);
  installOrchestrationRules();
  printPlaywrightHint();
}

function printSkills(integration) {
  console.log("\nAvailable skills:\n");
  skillEntries(integration).forEach((e) => console.log(`  ${e.name}/SKILL.md`));
  console.log(`  AGENT-BEHAVIOR.md`);
  console.log(`  ORCHESTRATION_RULES.md (workflow reference)`);
}

/** Recursively copy a directory tree. */
function copyDirRecursive(src, dest) {
  fs.mkdirSync(dest, { recursive: true });
  for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
    const srcPath  = path.join(src, entry.name);
    const destPath = path.join(dest, entry.name);
    if (entry.isDirectory()) {
      copyDirRecursive(srcPath, destPath);
    } else {
      fs.copyFileSync(srcPath, destPath);
    }
  }
}

function printPlaywrightHint() {
  console.log(`
  ${C.dim}Start Playwright MCP before running generation workflows:${C.reset}
  npx @playwright/mcp@latest --port 8931
`);
}

module.exports = async function skills(opts) {
  const target = (opts.target || "claude").toLowerCase();

  if (!fs.existsSync(SKILLS_DIR)) {
    console.error(`Skills directory not found: ${SKILLS_DIR}`);
    console.error("Try reinstalling: npm install -g @qa-gentic/stlc-agents");
    process.exit(1);
  }

  const integ = opts.integration || readIntegrationPrefSk() || "ado";
  switch (target) {
    case "claude":  installClaude(integ);  break;
    case "vscode":  installVscode(integ);  break;
    case "cursor":  installCursor(integ);  break;
    case "windsurf": installWindsurf(integ); break;
    case "both":    installClaude(integ); installVscode(integ); break;
    case "print":   printSkills(integ);   break;
    default:
      warn(`Unknown target: ${target}`);
      warn("Valid targets: claude, vscode, cursor, windsurf, both, print");
      process.exit(1);
  }
};