import { readdir, readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { homedir } from 'node:os';
import yaml from 'js-yaml';
// ── Category Derivation ──────────────────────────────────────────────────────
const CATEGORY_RULES = [
    { test: (name) => name.startsWith('shep-kit:'), category: 'Workflow' },
    { test: (name) => name.startsWith('shep:'), category: 'Code Generation' },
    { test: (name) => /(?:review|validate|cross-validate)/.test(name), category: 'Analysis' },
];
export function deriveCategory(name) {
    for (const rule of CATEGORY_RULES) {
        if (rule.test(name))
            return rule.category;
    }
    return 'Reference';
}
// ── Display Name ─────────────────────────────────────────────────────────────
const DISPLAY_NAME_PREFIXES = ['shep-kit:', 'shep:'];
export function getDisplayName(name) {
    for (const prefix of DISPLAY_NAME_PREFIXES) {
        if (name.startsWith(prefix))
            return name.slice(prefix.length);
    }
    return name;
}
export function parseFrontmatter(content) {
    const delimiterPattern = /^---\s*$/m;
    const firstMatch = content.match(delimiterPattern);
    if (firstMatch?.index === undefined)
        return null;
    const afterFirst = firstMatch.index + firstMatch[0].length;
    const rest = content.slice(afterFirst);
    const secondMatch = rest.match(delimiterPattern);
    if (secondMatch?.index === undefined)
        return null;
    const yamlContent = rest.slice(0, secondMatch.index);
    const body = rest.slice(secondMatch.index + secondMatch[0].length).trim();
    let parsed;
    try {
        parsed = yaml.load(yamlContent);
    }
    catch {
        return null;
    }
    if (!parsed || typeof parsed !== 'object')
        return null;
    const name = parsed['name'];
    const description = parsed['description'];
    if (typeof name !== 'string' || typeof description !== 'string')
        return null;
    return {
        name,
        description,
        context: typeof parsed['context'] === 'string' ? parsed['context'] : undefined,
        allowedTools: typeof parsed['allowed-tools'] === 'string' ? parsed['allowed-tools'] : undefined,
        body,
    };
}
// ── Resource Detection ───────────────────────────────────────────────────────
const KNOWN_RESOURCE_DIRS = [
    'references',
    'examples',
    'templates',
    'scripts',
    'validation',
    'rules',
];
async function detectResources(skillDir) {
    const resources = [];
    for (const dirName of KNOWN_RESOURCE_DIRS) {
        try {
            const entries = await readdir(join(skillDir, dirName));
            resources.push({ name: dirName, fileCount: entries.length });
        }
        catch {
            // Directory doesn't exist — skip
        }
    }
    return resources;
}
// ── Skill Directory Reader ───────────────────────────────────────────────────
async function getSkillsFromDirectory(dirPath, source) {
    let entries;
    try {
        const dirEntries = await readdir(dirPath, { withFileTypes: true });
        entries = dirEntries.filter((e) => e.isDirectory()).map((e) => e.name);
    }
    catch {
        return [];
    }
    const skills = [];
    for (const entry of entries) {
        const skillDir = join(dirPath, entry);
        const skillMdPath = join(skillDir, 'SKILL.md');
        let content;
        try {
            content = await readFile(skillMdPath, 'utf-8');
        }
        catch {
            continue;
        }
        const frontmatter = parseFrontmatter(content);
        if (!frontmatter) {
            // eslint-disable-next-line no-console
            console.warn(`Skipping skill "${entry}": invalid or missing frontmatter in SKILL.md`);
            continue;
        }
        const resources = await detectResources(skillDir);
        skills.push({
            name: frontmatter.name,
            displayName: getDisplayName(frontmatter.name),
            description: frontmatter.description,
            context: frontmatter.context,
            allowedTools: frontmatter.allowedTools,
            category: deriveCategory(frontmatter.name),
            source,
            body: frontmatter.body,
            resources,
        });
    }
    return skills;
}
export async function getSkills(projectRoot, homeDir) {
    const root = projectRoot ?? process.env.NEXT_PUBLIC_SHEP_INSTANCE_PATH ?? process.cwd();
    const home = homeDir ?? homedir();
    const projectDir = join(root, '.claude', 'skills');
    const globalDir = join(home, '.claude', 'skills');
    const [projectSkills, globalSkills] = await Promise.all([
        getSkillsFromDirectory(projectDir, 'project'),
        getSkillsFromDirectory(globalDir, 'global'),
    ]);
    // Deduplicate by name — project skills take precedence over global skills
    const seen = new Set(projectSkills.map((s) => s.name));
    const uniqueGlobalSkills = globalSkills.filter((s) => !seen.has(s.name));
    return [...projectSkills, ...uniqueGlobalSkills].sort((a, b) => a.name.localeCompare(b.name));
}
