#!/usr/bin/env node

import { readFile } from "node:fs/promises";
import path from "node:path";
import YAML from "yaml";

const ALLOWED_PROPERTIES = new Set([
  "name",
  "description",
  "license",
  "allowed-tools",
  "metadata",
  "compatibility",
]);

export async function readSkillMarkdown(skillPath) {
  const skillMdPath = path.join(skillPath, "SKILL.md");
  return readFile(skillMdPath, "utf8");
}

export function resolveSkillPath(skillPath) {
  const resolved = path.resolve(skillPath);
  if (path.basename(resolved).toLowerCase() === "skill.md") {
    return path.dirname(resolved);
  }
  return resolved;
}

export function parseSkillFrontmatter(content) {
  if (!content.startsWith("---")) {
    throw new Error("No YAML frontmatter found");
  }

  const match = content.match(/^---\n([\s\S]*?)\n---/);
  if (!match) {
    throw new Error("Invalid frontmatter format");
  }

  const frontmatter = YAML.parse(match[1]);
  if (!frontmatter || typeof frontmatter !== "object" || Array.isArray(frontmatter)) {
    throw new Error("Frontmatter must be a YAML dictionary");
  }

  return frontmatter;
}

export async function parseSkillFile(skillPath) {
  const resolvedSkillPath = resolveSkillPath(skillPath);
  const content = await readSkillMarkdown(resolvedSkillPath);
  const frontmatter = parseSkillFrontmatter(content);
  return {
    content,
    frontmatter,
    name: typeof frontmatter.name === "string" ? frontmatter.name : "",
    description: typeof frontmatter.description === "string" ? frontmatter.description : "",
  };
}

export function validateFrontmatter(frontmatter) {
  const unexpectedKeys = Object.keys(frontmatter).filter((key) => !ALLOWED_PROPERTIES.has(key));
  if (unexpectedKeys.length > 0) {
    return {
      valid: false,
      message:
        `Unexpected key(s) in SKILL.md frontmatter: ${unexpectedKeys.sort().join(", ")}. ` +
        `Allowed properties are: ${Array.from(ALLOWED_PROPERTIES).sort().join(", ")}`,
    };
  }

  if (!("name" in frontmatter)) {
    return { valid: false, message: "Missing 'name' in frontmatter" };
  }
  if (!("description" in frontmatter)) {
    return { valid: false, message: "Missing 'description' in frontmatter" };
  }

  const name = frontmatter.name;
  if (typeof name !== "string") {
    return { valid: false, message: `Name must be a string, got ${typeof name}` };
  }
  const trimmedName = name.trim();
  if (trimmedName) {
    if (!/^[a-z0-9-]+$/.test(trimmedName)) {
      return {
        valid: false,
        message: `Name '${trimmedName}' should be kebab-case (lowercase letters, digits, and hyphens only)`,
      };
    }
    if (trimmedName.startsWith("-") || trimmedName.endsWith("-") || trimmedName.includes("--")) {
      return {
        valid: false,
        message: `Name '${trimmedName}' cannot start/end with hyphen or contain consecutive hyphens`,
      };
    }
    if (trimmedName.length > 64) {
      return {
        valid: false,
        message: `Name is too long (${trimmedName.length} characters). Maximum is 64 characters.`,
      };
    }
  }

  const description = frontmatter.description;
  if (typeof description !== "string") {
    return { valid: false, message: `Description must be a string, got ${typeof description}` };
  }
  const trimmedDescription = description.trim();
  if (trimmedDescription) {
    if (trimmedDescription.includes("<") || trimmedDescription.includes(">")) {
      return { valid: false, message: "Description cannot contain angle brackets (< or >)" };
    }
    if (trimmedDescription.length > 1024) {
      return {
        valid: false,
        message: `Description is too long (${trimmedDescription.length} characters). Maximum is 1024 characters.`,
      };
    }
  }

  const compatibility = frontmatter.compatibility;
  if (compatibility !== undefined && compatibility !== null && compatibility !== "") {
    if (typeof compatibility !== "string") {
      return { valid: false, message: `Compatibility must be a string, got ${typeof compatibility}` };
    }
    if (compatibility.length > 500) {
      return {
        valid: false,
        message: `Compatibility is too long (${compatibility.length} characters). Maximum is 500 characters.`,
      };
    }
  }

  return { valid: true, message: "Skill is valid!" };
}
