/**
 * tools/manage-drift-handler.ts — Consolidated drift management handler (SPEC-559)
 *
 * Drift Contract (v2):
 *   Drift = spec criteria that cannot be matched to any code artifact in the project.
 *
 *   Detection: for each criterion in a spec, check whether a related code file or
 *   function exists using code_reality_checker output or file glob patterns.
 *
 *   NOT drift:
 *     - Implementation style differences (naming conventions, code patterns)
 *     - Test coverage gaps (tracked separately by coverage tooling)
 *     - Performance characteristics that were not specified as criteria
 *
 *   This redesigned contract eliminates historical false positives that occurred
 *   when heuristic matchers compared stylistic code differences against spec text.
 */
import { hashProjectPath } from '../storage/base-store.js';
import { resolveDriftViolations } from '../engine/drift/violation-resolver.js';
import { buildDriftMonitorConfig, computeSummaryReport } from '../engine/drift-monitor.js';
import { getDriftMonitorConfig, saveDriftMonitorConfig, getDriftAlertRules, getLastReportAt, updateLastReportAt, } from '../storage/drift-monitor-store.js';
import { startWatcher, stopWatcher, getWatcherState } from '../engine/drift-watcher/index.js';
import { listSpecs } from '../storage/spec-store.js';
// ---------------------------------------------------------------------------
// Main dispatcher
// ---------------------------------------------------------------------------
export async function handleManageDrift(args) {
    try {
        return await dispatch(args);
    }
    catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        return {
            content: [
                { type: 'text', text: `Error in manage_drift (${args.action}): ${message}` },
            ],
            isError: true,
        };
    }
}
async function dispatch(args) {
    switch (args.action) {
        case 'detect':
            return handleDetect(args);
        case 'summary':
            return handleSummary(args);
        case 'resolve':
            return handleResolve(args);
        case 'watch':
            return handleWatch(args);
        default: {
            const _exhaustive = args.action;
            return {
                content: [{ type: 'text', text: `Unknown action: ${String(_exhaustive)}` }],
                isError: true,
            };
        }
    }
}
// ---------------------------------------------------------------------------
// detect — find criteria without matching code artifacts
// ---------------------------------------------------------------------------
async function handleDetect(args) {
    const projectPath = args.projectPath ?? '';
    if (!projectPath) {
        return errorResult('detect requires projectPath');
    }
    const projectId = args.projectId ?? hashProjectPath(projectPath);
    const dryRun = args.dryRun ?? false;
    // Use violation resolver to identify unmatched criteria
    const result = await resolveDriftViolations(projectPath, projectId, true);
    const lines = [
        dryRun ? '[DRY RUN] Drift detection (v2 contract):' : 'Drift detection (v2 contract):',
        '',
        'Contract: drift = spec criteria with no matching code artifact.',
        '',
        `Unmatched criteria found: ${result.resolved.length + result.manualReview.length}`,
        `Auto-resolvable: ${result.resolved.length}`,
        `Requires manual review: ${result.manualReview.length}`,
    ];
    if (args.specId) {
        lines.push('', `Filtered to spec: ${args.specId}`);
    }
    if (result.resolved.length > 0) {
        lines.push('', 'Unmatched criteria (auto-resolvable):');
        for (const r of result.resolved) {
            lines.push(`  [${r.specId}] ${r.action}: ${r.description}`);
        }
    }
    if (result.manualReview.length > 0) {
        lines.push('', 'Unmatched criteria (manual review needed):');
        for (const r of result.manualReview) {
            lines.push(`  ${r}`);
        }
    }
    return { content: [{ type: 'text', text: lines.join('\n') }] };
}
// ---------------------------------------------------------------------------
// summary — current drift state across all specs
// ---------------------------------------------------------------------------
async function handleSummary(args) {
    const projectPath = args.projectPath ?? '';
    if (!projectPath) {
        return errorResult('summary requires projectPath');
    }
    const specList = args.specIds ?? [];
    const config = await getDriftMonitorConfig(projectPath);
    const rules = await getDriftAlertRules(projectPath);
    const lastReportAt = await getLastReportAt(projectPath);
    const report = await computeSummaryReport(projectPath, specList, config, rules);
    await updateLastReportAt(projectPath, report.generatedAt);
    const lines = [
        '**Drift Summary (v2 contract)**',
        '',
        `Previous report: ${lastReportAt ?? 'Never'}`,
        `Generated: ${report.generatedAt}`,
        '',
        `| Metric | Value |`,
        `|--------|-------|`,
        `| Total Specs | ${report.totalSpecs} |`,
        `| Drifted | ${report.driftedSpecs} |`,
        `| Clean | ${report.cleanSpecs} |`,
        `| Overall Drift Score | ${report.overallDriftScore}% |`,
    ];
    if (report.alerts.length > 0) {
        lines.push('', '**Alerts**', '');
        for (const alert of report.alerts) {
            const rule = alert.ruleName !== undefined ? ` [${alert.ruleName}]` : '';
            lines.push(`- ${alert.specId}: score ${alert.driftScore}${rule}`);
        }
    }
    if (report.alerts.length === 0) {
        lines.push('', 'No alerts — all specs within threshold.');
    }
    return { content: [{ type: 'text', text: lines.join('\n') }] };
}
// ---------------------------------------------------------------------------
// resolve — mark drift items as resolved / create follow-up specs
// ---------------------------------------------------------------------------
async function handleResolve(args) {
    const projectPath = args.projectPath ?? '';
    if (!projectPath) {
        return errorResult('resolve requires projectPath');
    }
    const projectId = args.projectId ?? hashProjectPath(projectPath);
    const dryRun = args.dryRun ?? false;
    const result = await resolveDriftViolations(projectPath, projectId, dryRun);
    const lines = [
        dryRun ? '[DRY RUN] Drift resolution:' : 'Drift resolution:',
        '',
        `Violations resolved: ${result.resolved.length}`,
        `Follow-up specs created: ${result.followUpSpecsCreated.length}`,
        `Requiring manual review: ${result.manualReview.length}`,
    ];
    if (result.resolved.length > 0) {
        lines.push('', 'Resolved:');
        for (const r of result.resolved) {
            lines.push(`  [${r.specId}] ${r.action}: ${r.description}`);
        }
    }
    if (result.followUpSpecsCreated.length > 0) {
        lines.push('', 'Follow-up specs created:');
        for (const id of result.followUpSpecsCreated) {
            lines.push(`  + ${id}`);
        }
    }
    if (result.manualReview.length > 0) {
        lines.push('', 'Requiring manual review:');
        for (const r of result.manualReview) {
            lines.push(`  ${r}`);
        }
    }
    return { content: [{ type: 'text', text: lines.join('\n') }] };
}
// ---------------------------------------------------------------------------
// watch — start/stop/status for file-system watcher
// ---------------------------------------------------------------------------
async function handleWatch(args) {
    const projectPath = args.projectPath ?? '';
    const specId = args.specId ?? '';
    const watchAction = args.watchAction ?? 'status';
    if (!specId) {
        return errorResult('watch requires specId');
    }
    if (watchAction === 'status') {
        const state = getWatcherState(specId);
        if (!state) {
            return {
                content: [{ type: 'text', text: `No active watcher for spec ${specId}.` }],
            };
        }
        return {
            content: [
                {
                    type: 'text',
                    text: `Watcher status for ${specId}:\n${JSON.stringify(state, null, 2)}`,
                },
            ],
        };
    }
    if (watchAction === 'stop') {
        const stopped = stopWatcher(specId);
        return {
            content: [
                {
                    type: 'text',
                    text: stopped
                        ? `Watcher stopped for spec ${specId}.`
                        : `No active watcher found for spec ${specId}.`,
                },
            ],
        };
    }
    // watchAction === 'start'
    if (!projectPath) {
        return errorResult('watch start requires projectPath');
    }
    const projectId = args.projectId ?? hashProjectPath(projectPath);
    const specs = await listSpecs(projectId);
    const spec = specs.find((s) => s.id === specId);
    if (!spec) {
        return {
            content: [
                { type: 'text', text: `Spec ${specId} not found in project ${projectPath}.` },
            ],
        };
    }
    // Also enable drift monitoring config when starting a watcher
    const existing = await getDriftMonitorConfig(projectPath);
    const config = buildDriftMonitorConfig(projectPath, existing, true, existing?.scheduleHours ?? 24, existing?.threshold ?? 50);
    await saveDriftMonitorConfig(projectPath, config);
    const state = startWatcher({
        specId,
        projectPath,
        specPath: spec.specPath,
        watchedPaths: [projectPath],
    });
    return {
        content: [
            {
                type: 'text',
                text: `Watcher started for spec ${specId}.\nMonitoring: ${projectPath}\n${JSON.stringify(state, null, 2)}`,
            },
        ],
    };
}
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function errorResult(message) {
    return {
        content: [{ type: 'text', text: `Error: ${message}` }],
        isError: true,
    };
}
//# sourceMappingURL=manage-drift-handler.js.map