import { mkdir, mkdtemp, readFile, rm, symlink, writeFile } from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
import { DirectorySkillAdapter } from './skill-directory.js';
let tempDir;
let skillsDir;
async function writeSkill(directory, body) {
    await mkdir(directory, { recursive: true });
    await writeFile(path.join(directory, 'SKILL.md'), body, 'utf-8');
}
function buildSkill(name = 'frontend-design') {
    return {
        id: 'skill_test',
        name,
        directory: path.join(tempDir, 'source'),
        description: 'A design skill',
        apps: {
            claude: false,
            claudecode: true,
            codex: false,
            gemini: false,
            opencode: false,
            openclaw: false,
        },
        installedAt: Date.now(),
    };
}
beforeEach(async () => {
    tempDir = await mkdtemp(path.join(os.tmpdir(), 'skill-directory-adapter-'));
    skillsDir = path.join(tempDir, 'skills');
});
afterEach(async () => {
    await rm(tempDir, { recursive: true, force: true });
});
describe('DirectorySkillAdapter', () => {
    it('imports only skill directories with SKILL.md and parses front matter', async () => {
        await writeSkill(path.join(skillsDir, 'frontend-design'), '---\nname: Frontend Design\ndescription: Polished UI work\n---\n# Skill\n');
        await mkdir(path.join(skillsDir, 'ordinary-folder'), { recursive: true });
        await writeSkill(path.join(skillsDir, '.hidden-skill'), '---\nname: Hidden\n---\n');
        const adapter = new DirectorySkillAdapter('claudecode', skillsDir);
        const imported = await adapter.importSkills();
        expect(imported).toHaveLength(1);
        expect(imported[0]).toMatchObject({
            id: 'skill_import_claudecode_frontend-design',
            name: 'Frontend Design',
            description: 'Polished UI work',
            directory: path.join(skillsDir, 'frontend-design'),
        });
    });
    it('imports symlinked skill directories', async () => {
        const source = path.join(tempDir, 'linked-source');
        await writeSkill(source, '---\nname: Linked Skill\n---\n# Skill\n');
        await mkdir(skillsDir, { recursive: true });
        await symlink(source, path.join(skillsDir, 'linked-skill'), 'junction');
        const adapter = new DirectorySkillAdapter('opencode', skillsDir);
        const imported = await adapter.importSkills();
        expect(imported).toHaveLength(1);
        expect(imported[0]?.name).toBe('Linked Skill');
    });
    it('syncs and removes skill directories', async () => {
        const source = path.join(tempDir, 'source');
        await writeSkill(source, '# Skill\n');
        await writeFile(path.join(source, 'README.md'), 'hello', 'utf-8');
        const adapter = new DirectorySkillAdapter('codex', skillsDir);
        await adapter.syncSkill(buildSkill('copied-skill'), source, 'copy');
        const copiedReadme = await readFile(path.join(skillsDir, 'copied-skill', 'README.md'), 'utf-8');
        expect(copiedReadme).toBe('hello');
        await adapter.removeSkill(buildSkill('copied-skill'));
        const imported = await adapter.importSkills();
        expect(imported).toHaveLength(0);
    });
});
