// tools/log-decision.ts — Decision Log tool handler (SPEC-040)
// Operations: register | list | supersede | search
import { randomUUID } from 'node:crypto';
import * as decisionStorage from '../storage/decision-store.js';
import { knowledgeStore } from '../storage/index.js';
import { findConflictingDecisions, searchDecisions, categorizeDecision, } from '../engine/decision-store.js';
import { notifyStoreChange } from '../engine/doc-generator/portal/regen-hook.js';
// ---------------------------------------------------------------------------
// Main handler
// ---------------------------------------------------------------------------
export async function handleLogDecision(args) {
    const { projectId, operation } = args;
    try {
        const knowledge = await knowledgeStore.getKnowledge(projectId);
        if (!knowledge) {
            return errorResult(`Project "${projectId}" not found. Run init_project first.`);
        }
        switch (operation) {
            case 'register': {
                const result = await handleRegister(projectId, args);
                if (!result.isError) {
                    notifyStoreChange(knowledge.projectPath, 'decisions');
                }
                return result;
            }
            case 'list':
                return await handleList(projectId, args.query);
            case 'supersede': {
                const result = await handleSupersede(projectId, args.decisionId);
                if (!result.isError) {
                    notifyStoreChange(knowledge.projectPath, 'decisions');
                }
                return result;
            }
            case 'search':
                return await handleSearch(projectId, args.query);
            /* v8 ignore start */
            default: {
                const _exhaustive = operation;
                return errorResult(`Unknown operation: ${String(_exhaustive)}`);
            }
            /* v8 ignore stop */
        }
    }
    catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        return errorResult(`log_decision error: ${message}`);
    }
}
// ---------------------------------------------------------------------------
// Operation handlers
// ---------------------------------------------------------------------------
async function handleRegister(projectId, args) {
    if (!args.decision) {
        return errorResult('operation "register" requires a decision object.');
    }
    const { what, why, alternatives = [], decidedBy = 'both', category, specId } = args.decision;
    if (!what || !why) {
        return errorResult('"what" and "why" are required fields for a decision.');
    }
    const resolvedCategory = category ?? categorizeDecision(what, why);
    const existing = await decisionStorage.getDecisions(projectId);
    const conflicts = findConflictingDecisions(what, existing);
    const decision = {
        id: randomUUID(),
        what,
        why,
        alternatives,
        decidedBy,
        category: resolvedCategory,
        status: 'active',
        specId,
        date: new Date().toISOString(),
    };
    await decisionStorage.saveDecision(projectId, decision);
    const conflictWarning = conflicts.length > 0 ? formatConflictWarning(conflicts) : '';
    const text = `## Decision Registered\n\n` +
        `**ID**: \`${decision.id}\`\n` +
        `**What**: ${decision.what}\n` +
        `**Why**: ${decision.why}\n` +
        `**Category**: ${decision.category}\n` +
        `**Decided by**: ${decision.decidedBy}\n` +
        `**Date**: ${decision.date}\n` +
        (decision.specId ? `**Spec**: ${decision.specId}\n` : '') +
        (alternatives.length > 0 ? `**Alternatives considered**: ${alternatives.join(', ')}\n` : '') +
        conflictWarning;
    return { content: [{ type: 'text', text }] };
}
async function handleList(projectId, specFilter) {
    const decisions = specFilter
        ? await decisionStorage.getDecisionsBySpec(projectId, specFilter)
        : await decisionStorage.getAllDecisions(projectId);
    if (decisions.length === 0) {
        return { content: [{ type: 'text', text: 'No decisions recorded for this project yet.' }] };
    }
    const sorted = [...decisions].sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
    const rows = sorted
        .map((d) => `### ${d.category.toUpperCase()} — ${d.what}\n` +
        `- **ID**: \`${d.id}\`\n` +
        `- **Why**: ${d.why}\n` +
        `- **Status**: ${d.status}\n` +
        `- **Date**: ${d.date}\n` +
        (d.specId ? `- **Spec**: ${d.specId}\n` : ''))
        .join('\n');
    const text = `## Decision Log (${sorted.length} entries)\n\n${rows}`;
    return { content: [{ type: 'text', text }] };
}
async function handleSupersede(projectId, decisionId) {
    if (!decisionId) {
        return errorResult('operation "supersede" requires decisionId.');
    }
    const updated = await decisionStorage.updateDecision(projectId, decisionId, {
        status: 'superseded',
    });
    const text = `## Decision Superseded\n\n` +
        `Decision \`${updated.id}\` has been marked as **superseded**.\n\n` +
        `**Was**: ${updated.what}\n` +
        `It remains in the history for reference.`;
    return { content: [{ type: 'text', text }] };
}
async function handleSearch(projectId, query) {
    if (!query) {
        return errorResult('operation "search" requires a query string.');
    }
    const all = await decisionStorage.getAllDecisions(projectId);
    const results = searchDecisions(query, all);
    if (results.length === 0) {
        return {
            content: [{ type: 'text', text: `No decisions found matching "${query}".` }],
        };
    }
    const rows = results
        .map((d) => `- [\`${d.id}\`] **${d.what}** (${d.category}, ${d.status}) — ${d.why}`)
        .join('\n');
    const text = `## Search Results for "${query}" (${results.length} found)\n\n${rows}`;
    return { content: [{ type: 'text', text }] };
}
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function formatConflictWarning(conflicts) {
    const list = conflicts.map((d) => `  - [${d.date.slice(0, 10)}] ${d.what}`).join('\n');
    return (`\n> **Potential conflicts detected** with existing decisions:\n${list}\n` +
        `> Review these before proceeding. Use \`supersede\` if this decision replaces them.\n`);
}
function errorResult(message) {
    return { content: [{ type: 'text', text: message }], isError: true };
}
//# sourceMappingURL=log-decision.js.map