/**
 * Logica de instalacao de skills — port de mcp/tools/dev/skills_installer.py
 */

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

// ── Localizar pasta Skills Fluig ─────────────────────────────

function findSkillsDir() {
  // 1. Variavel de ambiente
  const envSrc = process.env.FLUIG_SKILLS_SOURCE;
  if (envSrc) {
    const skills = path.join(envSrc, "skills");
    if (fs.existsSync(skills)) return skills;
  }

  // 2. Relativo ao pacote: <pkg>/Skills Fluig/
  const pkgRoot = path.join(__dirname, "..", "..", "..");
  const fromPkg = path.join(pkgRoot, "Skills Fluig");
  if (fs.existsSync(fromPkg)) return fromPkg;

  // 3. cwd/Skills Fluig/
  const fromCwd = path.join(process.cwd(), "Skills Fluig");
  if (fs.existsSync(fromCwd)) return fromCwd;

  return null;
}

function findAgentsDir() {
  const envSrc = process.env.FLUIG_SKILLS_SOURCE;
  if (envSrc) {
    const d = path.join(envSrc, "agents");
    if (fs.existsSync(d)) return d;
  }
  // Tentar buscar em locais comuns do pacote fonte original
  const pkgRoot = path.join(__dirname, "..", "..", "..");
  const candidates = [
    path.join(pkgRoot, ".claude", "agents"),
    path.join(pkgRoot, "agents"),
  ];
  for (const c of candidates) {
    if (fs.existsSync(c)) return c;
  }
  return null;
}

function findRulesDir() {
  const envSrc = process.env.FLUIG_SKILLS_SOURCE;
  if (envSrc) {
    const d = path.join(envSrc, "rules");
    if (fs.existsSync(d)) return d;
  }
  const pkgRoot = path.join(__dirname, "..", "..", "..");
  const candidates = [
    path.join(pkgRoot, ".claude", "rules"),
    path.join(pkgRoot, "rules"),
  ];
  for (const c of candidates) {
    if (fs.existsSync(c)) return c;
  }
  return null;
}

// ── Listar skills disponiveis ────────────────────────────────

function listAvailableSkills() {
  const skillsPath = findSkillsDir();
  if (!skillsPath) return [];

  const skills = [];
  let entries;
  try {
    entries = fs.readdirSync(skillsPath).sort();
  } catch (_) {
    return [];
  }

  for (const nome of entries) {
    const skillPath = path.join(skillsPath, nome);
    if (!fs.statSync(skillPath).isDirectory()) continue;

    let descricao = "";
    const skillMd = path.join(skillPath, "SKILL.md");
    if (fs.existsSync(skillMd)) {
      const conteudo = fs.readFileSync(skillMd, "utf-8");
      const linhas = conteudo.split("\n").map((l) => l.trim()).filter(Boolean);
      descricao = linhas.find((l) => !l.startsWith("#")) || (linhas[0] || "");
      descricao = descricao.substring(0, 120);
    }

    skills.push({ nome, descricao, caminho: skillPath });
  }
  return skills;
}

// ── Ler conteudo da skill ────────────────────────────────────

function readSkillMd(skillPath) {
  const f = path.join(skillPath, "SKILL.md");
  return fs.existsSync(f) ? fs.readFileSync(f, "utf-8") : "";
}

function readTemplates(skillPath) {
  const tplDir = path.join(skillPath, "templates");
  if (!fs.existsSync(tplDir)) return [];

  const results = [];
  function walk(dir) {
    for (const entry of fs.readdirSync(dir)) {
      const full = path.join(dir, entry);
      if (fs.statSync(full).isDirectory()) {
        walk(full);
      } else {
        const rel = path.relative(tplDir, full);
        try {
          results.push({ arquivo: rel, conteudo: fs.readFileSync(full, "utf-8") });
        } catch (_) {}
      }
    }
  }
  walk(tplDir);
  return results;
}

function readReferences(skillPath) {
  const refDir = path.join(skillPath, "references");
  if (!fs.existsSync(refDir)) return [];

  const results = [];
  for (const f of fs.readdirSync(refDir).sort()) {
    const full = path.join(refDir, f);
    if (fs.statSync(full).isFile()) {
      try {
        results.push({ arquivo: f, conteudo: fs.readFileSync(full, "utf-8") });
      } catch (_) {}
    }
  }
  return results;
}

function skillToMarkdown(nome, skillPath) {
  const partes = [`# Fluig Skill: ${nome}\n`];

  const md = readSkillMd(skillPath);
  if (md) {
    partes.push(md);
    partes.push("\n---\n");
  }

  const refs = readReferences(skillPath);
  if (refs.length) {
    partes.push("## Refer\u00EAncias\n");
    for (const r of refs) {
      partes.push(`### ${r.arquivo}\n\`\`\`\n${r.conteudo}\n\`\`\`\n`);
    }
  }

  const templates = readTemplates(skillPath);
  if (templates.length) {
    partes.push("## Templates\n");
    for (const t of templates) {
      const ext = path.extname(t.arquivo).replace(".", "");
      partes.push(`### ${t.arquivo}\n\`\`\`${ext}\n${t.conteudo}\n\`\`\`\n`);
    }
  }

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

function skillToMdc(nome, skillPath) {
  const md = readSkillMd(skillPath);
  const linhas = md.split("\n").map((l) => l.trim()).filter(Boolean);
  const descricao = (linhas.find((l) => !l.startsWith("#")) || nome).substring(0, 200);

  const frontmatter = `---\ndescription: ${descricao}\nglobs:\nalwaysApply: false\n---\n`;
  const corpo = skillToMarkdown(nome, skillPath);
  return frontmatter + "\n" + corpo;
}

// ── Instaladores por destino ─────────────────────────────────

function installClaudeCode(skillNome, skillPath, destinoBase) {
  const dest = path.join(destinoBase, "skills", skillNome);
  if (fs.existsSync(dest)) {
    fs.rmSync(dest, { recursive: true, force: true });
  }
  fs.mkdirSync(path.dirname(dest), { recursive: true });
  fs.cpSync(skillPath, dest, { recursive: true });
  return `${skillNome} \u2192 ${dest}`;
}

function installCodex(skillNome, skillPath, destinoBase) {
  fs.mkdirSync(destinoBase, { recursive: true });
  const instrPath = path.join(destinoBase, "instructions.md");

  const novoConteudo = skillToMarkdown(skillNome, skillPath);

  let final;
  if (fs.existsSync(instrPath)) {
    let atual = fs.readFileSync(instrPath, "utf-8");
    const pattern = new RegExp(
      `# Fluig Skill: ${skillNome.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[\\s\\S]*?(?=\\n# Fluig Skill:|$)`,
    );
    atual = atual.replace(pattern, "").trim();
    final = atual + "\n\n" + novoConteudo;
  } else {
    final = novoConteudo;
  }

  fs.writeFileSync(instrPath, final.trim() + "\n", "utf-8");
  return `${skillNome} \u2192 ${instrPath}`;
}

function installCopilot(skillNome, skillPath, projetoPath) {
  const destDir = path.join(projetoPath, ".github");
  fs.mkdirSync(destDir, { recursive: true });
  const instrPath = path.join(destDir, "copilot-instructions.md");

  const novoConteudo = skillToMarkdown(skillNome, skillPath);

  let final;
  if (fs.existsSync(instrPath)) {
    let atual = fs.readFileSync(instrPath, "utf-8");
    const pattern = new RegExp(
      `# Fluig Skill: ${skillNome.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[\\s\\S]*?(?=\\n# Fluig Skill:|$)`,
    );
    atual = atual.replace(pattern, "").trim();
    final = atual + "\n\n" + novoConteudo;
  } else {
    final = novoConteudo;
  }

  fs.writeFileSync(instrPath, final.trim() + "\n", "utf-8");
  return `${skillNome} \u2192 ${instrPath}`;
}

function installCursor(skillNome, skillPath, projetoPath) {
  const destDir = path.join(projetoPath, ".cursor", "rules");
  fs.mkdirSync(destDir, { recursive: true });
  const mdcPath = path.join(destDir, `${skillNome}.mdc`);

  const conteudo = skillToMdc(skillNome, skillPath);
  fs.writeFileSync(mdcPath, conteudo, "utf-8");
  return `${skillNome} \u2192 ${mdcPath}`;
}

function installAgent(destinoBase) {
  const agentsDir = findAgentsDir();
  if (!agentsDir) return "\u26A0 Pasta agents/ nao encontrada na fonte";

  const src = path.join(agentsDir, "fluig-developer.md");
  if (!fs.existsSync(src)) return "\u26A0 fluig-developer.md nao encontrado na fonte";

  const destDir = path.join(destinoBase, "agents");
  fs.mkdirSync(destDir, { recursive: true });
  fs.copyFileSync(src, path.join(destDir, "fluig-developer.md"));
  return `fluig-developer.md \u2192 ${destDir}`;
}

function installRules(destinoBase) {
  const rulesDir = findRulesDir();
  if (!rulesDir) return ["\u26A0 Pasta rules/ nao encontrada na fonte"];

  const destDir = path.join(destinoBase, "rules");
  fs.mkdirSync(destDir, { recursive: true });

  const resultados = [];
  for (const f of fs.readdirSync(rulesDir)) {
    const src = path.join(rulesDir, f);
    if (fs.statSync(src).isFile()) {
      fs.copyFileSync(src, path.join(destDir, f));
      resultados.push(`${f} \u2192 ${destDir}`);
    }
  }
  return resultados;
}

module.exports = {
  findSkillsDir,
  listAvailableSkills,
  installClaudeCode,
  installCodex,
  installCopilot,
  installCursor,
  installAgent,
  installRules,
};
