// tools/spec-lint-handler.ts — Handler for Custom Spec Lint Rules Engine (SPEC-364)
import { loadLintRules, saveLintRule, deleteLintRule } from '../storage/spec-lint-rules-store.js';
import { generateRuleId, runLint, lintSpec } from '../engine/spec-lint-engine.js';
import { listSpecs, getSpec } from '../storage/spec-store.js';
import { hashProjectPath } from '../storage/base-store.js';
export async function handleDefineLintRule(input) {
    const { projectPath, name, description, when, then, severity, appliesTo } = input;
    try {
        const id = generateRuleId(name);
        const rule = {
            id,
            name,
            description,
            then,
            severity,
            appliesTo,
            createdAt: new Date().toISOString(),
            ...(when !== undefined ? { when } : {}),
        };
        await saveLintRule(projectPath, rule);
        return {
            content: [
                {
                    type: 'text',
                    text: `Lint rule "${name}" created (id: ${id}).`,
                },
            ],
        };
    }
    catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        return {
            content: [{ type: 'text', text: `Failed to define lint rule: ${message}` }],
            isError: true,
        };
    }
}
export async function handleListLintRules(input) {
    const { projectPath } = input;
    try {
        const rules = await loadLintRules(projectPath);
        if (rules.length === 0) {
            return {
                content: [
                    { type: 'text', text: 'No lint rules defined. Use define_spec_lint_rule to add rules.' },
                ],
            };
        }
        const lines = rules.map((r) => `- [${r.id}] "${r.name}" (${r.severity}): ${r.description}` +
            ` | applies to: ${r.appliesTo.all === true ? 'all' : `tags [${(r.appliesTo.tags ?? []).join(', ')}]`}`);
        return {
            content: [
                {
                    type: 'text',
                    text: `Lint rules (${String(rules.length)}):\n${lines.join('\n')}`,
                },
            ],
        };
    }
    catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        return {
            content: [{ type: 'text', text: `Failed to list lint rules: ${message}` }],
            isError: true,
        };
    }
}
export async function handleRunSpecLint(input) {
    const { projectPath, specId } = input;
    try {
        const projectId = hashProjectPath(projectPath);
        const rules = await loadLintRules(projectPath);
        if (rules.length === 0) {
            return {
                content: [
                    {
                        type: 'text',
                        text: 'No lint rules defined. Use define_spec_lint_rule to add rules first.',
                    },
                ],
            };
        }
        if (specId !== undefined) {
            const spec = await getSpec(projectId, specId);
            if (spec === null) {
                return {
                    content: [{ type: 'text', text: `Spec "${specId}" not found.` }],
                    isError: true,
                };
            }
            const violations = lintSpec(spec, rules);
            if (violations.length === 0) {
                return {
                    content: [{ type: 'text', text: `Spec "${specId}" passed all lint rules.` }],
                };
            }
            const lines = violations.map((v) => `[${v.severity.toUpperCase()}] ${v.message} (rule: ${v.ruleName}, field: ${v.field})`);
            return {
                content: [
                    {
                        type: 'text',
                        text: `Lint violations for ${specId} (${String(violations.length)}):\n${lines.join('\n')}`,
                    },
                ],
            };
        }
        // Run on all specs
        const specs = await listSpecs(projectId);
        const result = runLint(specs, rules);
        result.projectPath = projectPath;
        if (result.violations.length === 0) {
            return {
                content: [
                    {
                        type: 'text',
                        text: `All ${String(specs.length)} specs passed lint checks. ` +
                            `Rules applied: ${String(result.rulesApplied)}.`,
                    },
                ],
            };
        }
        const lines = result.violations.map((v) => `[${v.severity.toUpperCase()}] ${v.specId} — ${v.message} (rule: ${v.ruleName})`);
        return {
            content: [
                {
                    type: 'text',
                    text: `Lint results: ${String(result.errorCount)} errors, ${String(result.warningCount)} warnings ` +
                        `across ${String(result.failedSpecs)} spec(s). ` +
                        `Passed: ${String(result.passedSpecs)}/${String(specs.length)}.\n\n` +
                        lines.join('\n'),
                },
            ],
        };
    }
    catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        return {
            content: [{ type: 'text', text: `Failed to run spec lint: ${message}` }],
            isError: true,
        };
    }
}
export async function handleDeleteLintRule(input) {
    const { projectPath, ruleId } = input;
    try {
        const deleted = await deleteLintRule(projectPath, ruleId);
        if (!deleted) {
            return {
                content: [{ type: 'text', text: `Lint rule "${ruleId}" not found.` }],
                isError: true,
            };
        }
        return {
            content: [{ type: 'text', text: `Lint rule "${ruleId}" deleted successfully.` }],
        };
    }
    catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        return {
            content: [{ type: 'text', text: `Failed to delete lint rule: ${message}` }],
            isError: true,
        };
    }
}
//# sourceMappingURL=spec-lint-handler.js.map