// engine/universal-rules/host-writer.ts — SPEC-779
// Write a UniversalRule to disk using the appropriate host strategy.
import { readFile, mkdir, writeFile } from 'node:fs/promises';
import { join } from 'node:path';
import { assertEnglishOnlyArtifactText } from '../spec-language/english-only.js';
// ---------------------------------------------------------------------------
// Claude Code writer
// ---------------------------------------------------------------------------
/**
 * Write a rule to `.claude/rules/{id}.md` for Claude Code projects.
 * Returns the absolute path written.
 */
async function writeForClaudeCode(rule, projectPath) {
    const rulesDir = join(projectPath, '.claude', 'rules');
    await mkdir(rulesDir, { recursive: true });
    const filePath = join(rulesDir, `${rule.id}.md`);
    const content = rule.buildContent('claude-code');
    assertEnglishOnlyArtifactText(`${rule.name}\n\n${rule.description}\n\n${content}`, 'rule');
    await writeFile(filePath, content, 'utf-8');
    return filePath;
}
// ---------------------------------------------------------------------------
// Codex writer  (block-marker strategy in AGENTS.md)
// ---------------------------------------------------------------------------
const AGENTS_MD_FILE = 'AGENTS.md';
const OPEN_MARKER = (id) => `<!-- planu:rules:${id} -->`;
const CLOSE_MARKER = (id) => `<!-- /planu:rules:${id} -->`;
/**
 * Write / replace a rule block inside AGENTS.md.
 * Creates the file if it doesn't exist.
 * Returns the absolute path of AGENTS.md.
 */
async function writeForCodex(rule, projectPath) {
    const agentsMdPath = join(projectPath, AGENTS_MD_FILE);
    let existing;
    try {
        existing = await readFile(agentsMdPath, 'utf-8');
    }
    catch {
        existing = '';
    }
    const open = OPEN_MARKER(rule.id);
    const close = CLOSE_MARKER(rule.id);
    const content = rule.buildContent('codex');
    assertEnglishOnlyArtifactText(`${rule.name}\n\n${rule.description}\n\n${content}`, 'rule');
    const block = `${open}\n${content}\n${close}`;
    // Replace existing block or append
    const openIdx = existing.indexOf(open);
    const closeIdx = existing.indexOf(close);
    let updated;
    if (openIdx !== -1 && closeIdx !== -1 && closeIdx > openIdx) {
        updated = existing.slice(0, openIdx) + block + existing.slice(closeIdx + close.length);
    }
    else {
        updated = existing.length > 0 ? `${existing}\n\n${block}\n` : `${block}\n`;
    }
    await writeFile(agentsMdPath, updated, 'utf-8');
    return agentsMdPath;
}
// ---------------------------------------------------------------------------
// Gemini writer (block-marker strategy in .gemini/conventions.md)
// ---------------------------------------------------------------------------
const GEMINI_CONVENTIONS_FILE = join('.gemini', 'conventions.md');
/**
 * Write / replace a rule block inside .gemini/conventions.md.
 * Creates the file if it doesn't exist.
 * Returns the absolute path of conventions.md.
 */
async function writeForGemini(rule, projectPath) {
    const conventionsPath = join(projectPath, GEMINI_CONVENTIONS_FILE);
    await mkdir(join(projectPath, '.gemini'), { recursive: true });
    let existing;
    try {
        existing = await readFile(conventionsPath, 'utf-8');
    }
    catch {
        existing = '';
    }
    const open = OPEN_MARKER(rule.id);
    const close = CLOSE_MARKER(rule.id);
    const content = rule.buildContent('gemini');
    assertEnglishOnlyArtifactText(`${rule.name}\n\n${rule.description}\n\n${content}`, 'rule');
    const block = `${open}\n${content}\n${close}`;
    const openIdx = existing.indexOf(open);
    const closeIdx = existing.indexOf(close);
    let updated;
    if (openIdx !== -1 && closeIdx !== -1 && closeIdx > openIdx) {
        updated = existing.slice(0, openIdx) + block + existing.slice(closeIdx + close.length);
    }
    else {
        updated = existing.length > 0 ? `${existing}\n\n${block}\n` : `${block}\n`;
    }
    await writeFile(conventionsPath, updated, 'utf-8');
    return conventionsPath;
}
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
/**
 * Write a rule to the host-appropriate location.
 * Returns the absolute path written (may be AGENTS.md or conventions.md for block-based hosts).
 */
export async function writeRuleForHost(rule, projectPath, host) {
    switch (host) {
        case 'claude-code':
            return writeForClaudeCode(rule, projectPath);
        case 'codex':
            return writeForCodex(rule, projectPath);
        case 'gemini':
            return writeForGemini(rule, projectPath);
    }
}
//# sourceMappingURL=host-writer.js.map