// tools/init-project/host-assets-writer.ts — Host-aware rules/skills installed by init_project
import { access, readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { detectHost } from '../../engine/host-detection/detect-host.js';
import { handleCreateSkill } from '../create-skill.js';
const CORE_SKILL_TEMPLATES = [
    'planu-new-spec.md',
    'planu-validate.md',
    'planu-release.md',
    'planu-resume-work.md',
    'planu-native.md',
    'planu-multi-teammate-review.md',
    'planu-context-assets.md',
];
async function fileExists(path) {
    try {
        await access(path);
        return true;
    }
    catch {
        return false;
    }
}
function addHost(hosts, host) {
    if (!hosts.includes(host)) {
        hosts.push(host);
    }
}
/**
 * Detect every project host that should receive Planu-owned assets.
 * Environment identifies the active MCP host; files identify other checked-in
 * host configs that should stay in sync too.
 */
export async function detectInitAssetHosts(projectPath) {
    const hosts = [];
    const activeHost = detectHost();
    if (activeHost === 'claude-code' || activeHost === 'codex' || activeHost === 'gemini') {
        addHost(hosts, activeHost);
    }
    const checks = await Promise.all([
        fileExists(join(projectPath, 'CLAUDE.md')),
        fileExists(join(projectPath, '.claude')),
        fileExists(join(projectPath, 'AGENTS.md')),
        fileExists(join(projectPath, '.openai')),
        fileExists(join(projectPath, 'GEMINI.md')),
        fileExists(join(projectPath, '.gemini')),
        fileExists(join(projectPath, 'opencode.json')),
        fileExists(join(projectPath, '.opencode')),
    ]);
    const [hasClaudeMd, hasClaudeDir, hasAgentsMd, hasOpenAiDir, hasGeminiMd, hasGeminiDir, hasOpenCodeJson, hasOpenCodeDir,] = checks;
    if (hasClaudeMd || hasClaudeDir) {
        addHost(hosts, 'claude-code');
    }
    if (hasAgentsMd || hasOpenAiDir) {
        addHost(hosts, 'codex');
    }
    if (hasGeminiMd || hasGeminiDir) {
        addHost(hosts, 'gemini');
    }
    if (hasOpenCodeJson || hasOpenCodeDir) {
        addHost(hosts, 'opencode');
    }
    // Portable default for new/unknown projects: AGENTS.md, not Claude-specific files.
    if (hosts.length === 0) {
        addHost(hosts, 'codex');
    }
    return hosts;
}
async function installRulesForHost(projectPath, host) {
    try {
        const { installUniversalRules } = await import('../../engine/universal-rules/installer.js');
        return await installUniversalRules(projectPath, host);
    }
    catch {
        return [];
    }
}
function parseSkillTemplate(raw, fallbackName) {
    const frontmatter = /^---\n([\s\S]*?)\n---\n?/.exec(raw);
    const name = /(?:^|\n)name:\s*([^\n]+)/.exec(frontmatter?.[1] ?? '')?.[1]?.trim() ??
        fallbackName.replace(/\.md$/, '');
    const description = /(?:^|\n)description:\s*([^\n]+)/.exec(frontmatter?.[1] ?? '')?.[1]?.trim() ??
        `Planu workflow skill: ${name}`;
    const content = frontmatter ? raw.slice(frontmatter[0].length) : raw;
    return {
        name,
        description: description.replace(/^["']|["']$/g, ''),
        content: content.trimEnd() + '\n',
    };
}
async function readCoreSkillTemplate(fileName) {
    try {
        const { fileURLToPath } = await import('node:url');
        const templatePath = join(fileURLToPath(new URL('.', import.meta.url)), '../../config/skill-templates', fileName);
        const raw = await readFile(templatePath, 'utf-8');
        return parseSkillTemplate(raw, fileName);
    }
    catch {
        return null;
    }
}
async function installCoreSkillsForHost(projectPath, host) {
    const installed = [];
    for (const fileName of CORE_SKILL_TEMPLATES) {
        const template = await readCoreSkillTemplate(fileName);
        if (template === null) {
            continue;
        }
        const result = await handleCreateSkill({
            projectPath,
            host,
            name: template.name,
            description: template.description,
            content: template.content,
            overwriteExisting: false,
        });
        if (result.isError === true) {
            continue;
        }
        const path = typeof result.structuredContent === 'object' &&
            'skillFilePath' in result.structuredContent &&
            typeof result.structuredContent.skillFilePath === 'string'
            ? result.structuredContent.skillFilePath
            : host === 'codex'
                ? join(projectPath, 'AGENTS.md')
                : host === 'gemini'
                    ? join(projectPath, '.gemini', 'skills', `${template.name}.md`)
                    : join(projectPath, '.claude', 'skills', template.name, 'SKILL.md');
        installed.push({ host, name: template.name, path });
    }
    return installed;
}
async function scaffoldHostConfig(projectPath, host) {
    try {
        if (host === 'codex') {
            const { scaffoldCodexConfig } = await import('../../hosts/codex/config-scaffold.js');
            await scaffoldCodexConfig(projectPath);
            return true;
        }
        if (host === 'gemini') {
            const { scaffoldGeminiConfig } = await import('../../hosts/gemini/config-scaffold.js');
            await scaffoldGeminiConfig(projectPath);
            return true;
        }
        if (host === 'opencode') {
            const { scaffoldOpenCodeConfig } = await import('../../engine/opencode/config-scaffold.js');
            scaffoldOpenCodeConfig(projectPath);
            return true;
        }
    }
    catch {
        return false;
    }
    return false;
}
export async function installInitHostAssets(projectPath, _knowledge) {
    const detectedHosts = await detectInitAssetHosts(projectPath);
    const rulesInstalled = [];
    const skillsInstalled = [];
    let opencodeConfigured = false;
    for (const host of detectedHosts) {
        const configured = await scaffoldHostConfig(projectPath, host);
        if (host === 'opencode') {
            opencodeConfigured ||= configured;
            continue;
        }
        rulesInstalled.push(...(await installRulesForHost(projectPath, host)));
        skillsInstalled.push(...(await installCoreSkillsForHost(projectPath, host)));
    }
    return { detectedHosts, rulesInstalled, skillsInstalled, opencodeConfigured };
}
//# sourceMappingURL=host-assets-writer.js.map