#!/usr/bin/env node
/**
 * Sync marketplace.json and README.md with skills directory.
 *
 * Scans the skills/ directory for valid skills (directories containing SKILL.md)
 * and updates marketplace.json and the README skills table to match.
 */

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

const SKILLS_DIR = "skills";
const MARKETPLACE_FILE = ".claude-plugin/marketplace.json";
const PLUGIN_FILE = ".claude-plugin/plugin.json";
const README_FILE = "README.md";

/**
 * Parse YAML frontmatter from a SKILL.md file
 */
function parseFrontmatter(content) {
  const match = content.match(/^---\n([\s\S]*?)\n---/);
  if (!match) return {};

  const frontmatter = {};
  const lines = match[1].split("\n");

  for (const line of lines) {
    const colonIndex = line.indexOf(":");
    if (colonIndex === -1) continue;

    const key = line.slice(0, colonIndex).trim();
    let value = line.slice(colonIndex + 1).trim();

    // Remove quotes if present
    if ((value.startsWith('"') && value.endsWith('"')) ||
        (value.startsWith("'") && value.endsWith("'"))) {
      value = value.slice(1, -1);
    }

    frontmatter[key] = value;
  }

  return frontmatter;
}

/**
 * Get all skills with their metadata
 */
function getSkillsWithMetadata() {
  if (!fs.existsSync(SKILLS_DIR)) {
    return [];
  }

  return fs
    .readdirSync(SKILLS_DIR, { withFileTypes: true })
    .filter((entry) => {
      if (!entry.isDirectory()) return false;
      const skillFile = path.join(SKILLS_DIR, entry.name, "SKILL.md");
      return fs.existsSync(skillFile);
    })
    .map((entry) => {
      const skillFile = path.join(SKILLS_DIR, entry.name, "SKILL.md");
      const content = fs.readFileSync(skillFile, "utf8");
      const frontmatter = parseFrontmatter(content);

      return {
        dir: entry.name,
        path: `./${SKILLS_DIR}/${entry.name}`,
        name: frontmatter.name || entry.name,
        description: frontmatter.description || "",
      };
    })
    .sort((a, b) => a.name.localeCompare(b.name));
}

/**
 * Update skill count in description
 */
function updateSkillCount(description, count) {
  return description.replace(/\d+ marketing skills/, `${count} marketing skills`);
}

/**
 * Truncate description to a maximum length
 */
function truncateDescription(description, maxLength = 120) {
  if (description.length <= maxLength) return description;

  // Find last space before maxLength to avoid cutting words
  const truncated = description.slice(0, maxLength);
  const lastSpace = truncated.lastIndexOf(" ");

  return truncated.slice(0, lastSpace) + "...";
}

/**
 * Generate the skills table for README
 */
function generateSkillsTable(skills) {
  const header = "| Skill | Description |\n|-------|-------------|";
  const rows = skills.map((skill) => {
    const link = `[${skill.name}](skills/${skill.dir}/)`;
    const description = truncateDescription(skill.description);
    return `| ${link} | ${description} |`;
  });

  return [header, ...rows].join("\n");
}

/**
 * Update README.md with new skills table
 */
function updateReadme(skills) {
  const content = fs.readFileSync(README_FILE, "utf8");

  // Match content between skill list markers
  const tableRegex = /(<!-- SKILLS:START -->\n)[\s\S]*?(\n<!-- SKILLS:END -->)/;
  const newTable = generateSkillsTable(skills);

  if (!tableRegex.test(content)) {
    console.log("WARNING: Could not find skill markers in README.md");
    return false;
  }

  const newContent = content.replace(tableRegex, `$1${newTable}$2`);

  if (newContent === content) {
    return false;
  }

  fs.writeFileSync(README_FILE, newContent);
  return true;
}

/**
 * Update marketplace.json — refresh the skill count in the plugin description
 * and strip any `skills` array if present. Claude Code's plugin schema discovers
 * skills via the `skills/` directory; the explicit array fails validation, so
 * this script must never (re-)introduce it.
 */
function updateMarketplace(skills) {
  const marketplace = JSON.parse(fs.readFileSync(MARKETPLACE_FILE, "utf8"));
  const plugin = marketplace.plugins[0];

  const oldDescription = plugin.description;
  const newDescription = updateSkillCount(plugin.description, skills.length);
  const hadStaleSkillsArray = "skills" in plugin;

  if (newDescription === oldDescription && !hadStaleSkillsArray) {
    return { updated: false };
  }

  plugin.description = newDescription;
  delete plugin.skills;

  fs.writeFileSync(MARKETPLACE_FILE, JSON.stringify(marketplace, null, 2) + "\n");

  return { updated: true, removedSkillsArray: hadStaleSkillsArray };
}

/**
 * Update plugin.json's `version` field to match marketplace.json's
 * `metadata.version`. Claude Code uses plugin.json's version for the update
 * check (`claude plugin update`); if it drifts from marketplace.json the
 * update path silently breaks.
 */
function updatePluginVersion() {
  if (!fs.existsSync(PLUGIN_FILE)) return { updated: false };

  const marketplace = JSON.parse(fs.readFileSync(MARKETPLACE_FILE, "utf8"));
  const plugin = JSON.parse(fs.readFileSync(PLUGIN_FILE, "utf8"));
  const marketplaceVersion = marketplace.metadata && marketplace.metadata.version;

  if (!marketplaceVersion) return { updated: false };
  if (plugin.version === marketplaceVersion) return { updated: false };

  const oldVersion = plugin.version;
  plugin.version = marketplaceVersion;
  fs.writeFileSync(PLUGIN_FILE, JSON.stringify(plugin, null, 2) + "\n");
  return { updated: true, oldVersion, newVersion: marketplaceVersion };
}

function main() {
  const skills = getSkillsWithMetadata();

  const marketplaceResult = updateMarketplace(skills);
  const readmeUpdated = updateReadme(skills);
  const pluginResult = updatePluginVersion();

  if (!marketplaceResult.updated && !readmeUpdated && !pluginResult.updated) {
    console.log("Everything is already in sync");
    return;
  }

  if (marketplaceResult.updated) {
    if (marketplaceResult.removedSkillsArray) {
      console.log("Stripped stale `skills` array from marketplace.json");
    }
    console.log(`Updated marketplace.json (${skills.length} skills)`);
  }

  if (pluginResult.updated) {
    console.log(`Bumped plugin.json version: ${pluginResult.oldVersion} → ${pluginResult.newVersion}`);
  }

  if (readmeUpdated) {
    console.log("Updated README.md skills table");
  }
}

main();
