// @crash-shield-ignore-file — config/cache reader for Planu-controlled JSON; writer is this codebase, shape guaranteed by build/seed.
// engine/spec-cookbook.ts — SPEC-361: Spec Cookbook engine
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
// ---------------------------------------------------------------------------
// Catalog loading
// ---------------------------------------------------------------------------
let cachedCatalog = null;
export function loadCatalog() {
    if (cachedCatalog !== null) {
        return cachedCatalog;
    }
    const __dirname = dirname(fileURLToPath(import.meta.url));
    const catalogPath = join(__dirname, '..', 'config', 'spec-cookbook.json');
    try {
        const raw = readFileSync(catalogPath, 'utf-8');
        cachedCatalog = JSON.parse(raw);
        return cachedCatalog;
    }
    catch {
        return { version: '1.0.0', entries: [] };
    }
}
/** Exposed for testing: reset cached catalog */
export function resetCatalogCache() {
    cachedCatalog = null;
}
// ---------------------------------------------------------------------------
// List
// ---------------------------------------------------------------------------
export function listEntries(domain, featureType, limit = 50) {
    const catalog = loadCatalog();
    let entries = catalog.entries;
    if (domain !== undefined) {
        entries = entries.filter((e) => e.domain === domain);
    }
    if (featureType !== undefined) {
        const ft = featureType.toLowerCase();
        entries = entries.filter((e) => e.featureType.toLowerCase().includes(ft));
    }
    return entries.slice(0, limit);
}
// ---------------------------------------------------------------------------
// Get by ID
// ---------------------------------------------------------------------------
export function getEntry(id) {
    const catalog = loadCatalog();
    return catalog.entries.find((e) => e.id === id) ?? null;
}
// ---------------------------------------------------------------------------
// Search
// ---------------------------------------------------------------------------
export function searchEntries(query, limit = 20) {
    const catalog = loadCatalog();
    const q = query.toLowerCase();
    const scored = catalog.entries
        .map((e) => {
        let score = 0;
        if (e.id.toLowerCase().includes(q)) {
            score += 3;
        }
        if (e.title.toLowerCase().includes(q)) {
            score += 2;
        }
        if (e.description.toLowerCase().includes(q)) {
            score += 1;
        }
        if (e.tags.some((t) => t.toLowerCase().includes(q))) {
            score += 2;
        }
        if (e.featureType.toLowerCase().includes(q)) {
            score += 2;
        }
        if (e.domain.toLowerCase().includes(q)) {
            score += 1;
        }
        return { entry: e, score };
    })
        .filter((x) => x.score > 0)
        .sort((a, b) => b.score - a.score)
        .slice(0, limit);
    return scored.map((x) => x.entry);
}
// ---------------------------------------------------------------------------
// Apply — generate spec content with placeholders
// ---------------------------------------------------------------------------
export function applyEntry(entry, projectName) {
    const name = projectName ?? '[PROJECT_NAME]';
    const lines = [
        `---`,
        `title: "${entry.title}"`,
        `status: draft`,
        `domain: ${entry.domain}`,
        `feature_type: ${entry.featureType}`,
        `tags: [${entry.tags.map((t) => `"${t}"`).join(', ')}]`,
        `---`,
        ``,
        `# ${entry.title}`,
        ``,
        `**Project:** ${name}  `,
        `**Description:** ${entry.description}`,
        ``,
        `## Acceptance Criteria`,
        ``,
        ...entry.acceptanceCriteria.map((ac) => `- [ ] ${ac}`),
        ``,
        `## Technical Notes`,
        ``,
        `[PLACEHOLDER: Add implementation notes here]`,
        ``,
        `## Out of Scope`,
        ``,
        `[PLACEHOLDER: List what is NOT included in this spec]`,
        ``,
        `## Dependencies`,
        ``,
        `[PLACEHOLDER: List specs or services this depends on]`,
    ];
    if (entry.estimatedEffort !== undefined) {
        lines.splice(6, 0, `estimated_effort: "${entry.estimatedEffort}"`);
    }
    return {
        id: entry.id,
        title: entry.title,
        specContent: lines.join('\n'),
    };
}
// ---------------------------------------------------------------------------
// Contribute — add a new entry to the in-memory catalog
// ---------------------------------------------------------------------------
export function contributeEntry(entry) {
    const catalog = loadCatalog();
    const id = `${entry.domain}-${entry.featureType}-${String(Date.now()).slice(-6)}`;
    const newEntry = { ...entry, id };
    catalog.entries.push(newEntry);
    return newEntry;
}
// ---------------------------------------------------------------------------
// Format helpers
// ---------------------------------------------------------------------------
export function formatEntryMarkdown(entry) {
    const lines = [
        `## ${entry.title}`,
        ``,
        `**ID:** \`${entry.id}\` | **Domain:** ${entry.domain} | **Type:** ${entry.featureType}`,
        ``,
        entry.description,
        ``,
        `**Tags:** ${entry.tags.map((t) => `\`${t}\``).join(', ')}`,
    ];
    if (entry.estimatedEffort !== undefined) {
        lines.push(`**Estimated effort:** ${entry.estimatedEffort}`);
    }
    lines.push('', `**Acceptance Criteria:**`);
    for (const ac of entry.acceptanceCriteria) {
        lines.push(`- ${ac}`);
    }
    return lines.join('\n');
}
export function formatEntriesListMarkdown(entries) {
    if (entries.length === 0) {
        return 'No cookbook entries found matching your criteria.';
    }
    const lines = [
        `# Spec Cookbook (${String(entries.length)} entries)`,
        ``,
        `| ID | Domain | Type | Title |`,
        `|---|---|---|---|`,
    ];
    for (const e of entries) {
        lines.push(`| \`${e.id}\` | ${e.domain} | ${e.featureType} | ${e.title} |`);
    }
    lines.push('', `Use \`cookbook_get\` with an ID to see details, or \`cookbook_apply\` to generate a spec.`);
    return lines.join('\n');
}
//# sourceMappingURL=spec-cookbook.js.map