// tools/snapshot-spec-hashes.ts — Create/update hash snapshots for a spec
// Tracks file hashes and function signatures of files referenced in technical.md
import { specStore, knowledgeStore, hashSnapshotStore } from '../storage/index.js';
import { readSpecTechnicalSection } from '../engine/spec-format/read-technical-section.js';
import { createFileHashEntries, extractFilePlanPaths, extractSignaturesFromFiles, diffFileHashes, diffSignatures, } from '../engine/living-spec/index.js';
import { compactResult } from './output-formatter.js';
import { stripFrontmatter } from '../engine/frontmatter-parser.js';
export async function handleSnapshotSpecHashes(args) {
    const { projectId, specId } = args;
    // 1. Load spec
    const spec = await specStore.getSpec(projectId, specId);
    if (!spec) {
        return {
            content: [{ type: 'text', text: `Spec ${specId} not found` }],
            isError: true,
        };
    }
    // 2. Load project path
    const knowledge = await knowledgeStore.getKnowledge(projectId);
    if (!knowledge?.projectPath) {
        return {
            content: [{ type: 'text', text: 'Project not found. Run init_project first.' }],
            isError: true,
        };
    }
    const projectPath = knowledge.projectPath;
    // 3. Extract file paths from ## Technical section (unified spec.md) or legacy technical.md
    const technicalRaw = await readSpecTechnicalSection(spec);
    if (technicalRaw.length === 0) {
        return {
            content: [
                {
                    type: 'text',
                    text: `Could not read technical content for ${specId}. Ensure spec.md has a ## Technical section at ${spec.specPath}`,
                },
            ],
            isError: true,
        };
    }
    const filePaths = extractFilePlanPaths(stripFrontmatter(technicalRaw));
    if (filePaths.length === 0) {
        return {
            content: [
                {
                    type: 'text',
                    text: `No file paths found in technical.md File Plan section for ${specId}. Add files in a markdown table or list.`,
                },
            ],
        };
    }
    // 4. Create hash entries and extract signatures
    const files = await createFileHashEntries(projectPath, filePaths);
    const signatures = await extractSignaturesFromFiles(projectPath, filePaths);
    // 5. Load previous snapshot for comparison
    const previousSnapshot = await hashSnapshotStore.getSnapshot(projectId, specId);
    // 6. Save new snapshot
    const newSnapshot = {
        specId,
        createdAt: new Date().toISOString(),
        files,
        signatures,
    };
    await hashSnapshotStore.saveSnapshot(projectId, specId, newSnapshot);
    // 7. Generate diff report if previous snapshot exists
    let diffReport = null;
    if (previousSnapshot) {
        const fileDiffs = await diffFileHashes(projectPath, previousSnapshot, filePaths);
        const sigChanges = diffSignatures(previousSnapshot.signatures, signatures);
        diffReport = {
            changedFiles: fileDiffs.length,
            signatureChanges: sigChanges.length,
            details: {
                files: fileDiffs,
                signatures: sigChanges,
            },
        };
    }
    const message = previousSnapshot
        ? `Hash snapshot updated for ${specId}. ${String(diffReport?.changedFiles ?? 0)} file(s) changed.`
        : `Initial hash snapshot created for ${specId}.`;
    const lines = [
        message,
        `**filesTracked**: ${files.length}`,
        `**signaturesTracked**: ${signatures.length}`,
        `**totalPathsInPlan**: ${filePaths.length}`,
        `**missingFiles**: ${filePaths.length - files.length}`,
    ];
    if (diffReport) {
        lines.push('', '## Diff', `**changedFiles**: ${diffReport.changedFiles}`, `**signatureChanges**: ${diffReport.signatureChanges}`);
    }
    return compactResult(lines.join('\n'));
}
//# sourceMappingURL=snapshot-spec-hashes.js.map