import { z } from 'zod';
import { t } from '../../i18n/index.js';
import { safeTracked, safeLicensed } from '../safe-handler.js';
import { ChecklistFocusEnum, AuditCategoryEnum, SpecIdSchema } from '../schemas/index.js';
import { resolveProjectId, missingProjectIdError } from '../resolve-project-id.js';
import { handleDetectDrift } from '../detect-drift.js';
import { handleSummarizeSpec } from '../summarize-spec.js';
import { handleGenerateChecklist } from '../generate-checklist.js';
import { handleReconcileSpec } from '../reconcile-spec.js';
import { handleLearn } from '../learn.js';
import { handleAudit } from '../audit.js';
import { handleConsultDocs } from '../consult-docs.js';
import { handleDiscoverMcps } from '../discover-mcps.js';
import { handleSuggestMcps } from '../suggest-mcps.js';
import { handleAnalyzeSpecDependencies } from '../analyze-spec-dependencies.js';
import { handleSuggestMcpServer } from '../suggest-mcp-server.js';
import { handleScanOrphanSpecRefs, ScanOrphanSpecRefsInputSchema, } from '../scan-orphan-spec-refs.js';
import { registerGraphSpecsTool } from '../graph-specs.js';
import { registerAuditSpecsDriftTool } from '../audit-specs-drift.js';
import { handleSsrBackMigration } from '../ssr-back-migration.js';
/**
 * Registers drift detection, analysis, and discovery tools (tools 11–19) on the MCP server.
 */
// eslint-disable-next-line max-lines-per-function -- registry function: each tool definition is short
export function registerAnalysisTools(server) {
    // 11. detect_drift
    server.registerTool('detect_drift', {
        description: t('tools.detect_drift.description'),
        inputSchema: {
            specId: SpecIdSchema.describe('Spec ID to check'),
            projectId: z.string().max(500).optional().describe('Project ID hash. Prefer projectPath.'),
            projectPath: z
                .string()
                .max(4096)
                .optional()
                .describe('Absolute path to project root. Derives projectId automatically.'),
            mode: z
                .enum(['full', 'quick'])
                .optional()
                .describe('Analysis mode: full | quick (default: quick)'),
            outputFormat: z
                .enum(['report', 'ci-json', 'github-annotations'])
                .optional()
                .describe('Output format: report | ci-json | github-annotations'),
            threshold: z.number().optional().describe('Drift tolerance threshold 0-100 (default: 10)'),
        },
    }, safeTracked('detect_drift', async (args) => {
        const pid = resolveProjectId(args);
        if (!pid) {
            return missingProjectIdError;
        }
        return handleDetectDrift({ ...args, projectId: pid });
    }));
    // 12. summarize_spec
    server.registerTool('summarize_spec', {
        description: t('tools.summarize_spec.description'),
        annotations: { readOnlyHint: true },
        inputSchema: {
            specId: SpecIdSchema.describe('Spec ID to summarize'),
            projectId: z.string().max(500).optional().describe('Project ID hash. Prefer projectPath.'),
            projectPath: z
                .string()
                .max(4096)
                .optional()
                .describe('Absolute path to project root. Derives projectId automatically.'),
            format: z
                .enum(['executive', 'technical', 'oneliner'])
                .optional()
                .describe('Summary format: executive | technical | oneliner (default: technical)'),
        },
    }, safeTracked('summarize_spec', async (args) => {
        const pid = resolveProjectId(args);
        if (!pid) {
            return missingProjectIdError;
        }
        return handleSummarizeSpec({ ...args, projectId: pid });
    }));
    // 13. generate_checklist
    server.registerTool('generate_checklist', {
        description: t('tools.generate_checklist.description'),
        inputSchema: {
            specId: SpecIdSchema.describe('Spec ID'),
            projectId: z.string().max(500).optional().describe('Project ID hash. Prefer projectPath.'),
            projectPath: z
                .string()
                .max(4096)
                .optional()
                .describe('Absolute path to project root. Derives projectId automatically.'),
            focus: z
                .array(ChecklistFocusEnum)
                .max(100)
                .optional()
                .describe('Focus areas for the checklist'),
        },
    }, safeLicensed('generate_checklist', async (args) => {
        const pid = resolveProjectId(args);
        if (!pid) {
            return missingProjectIdError;
        }
        return handleGenerateChecklist({ ...args, projectId: pid });
    }));
    // 14. reconcile_spec
    server.registerTool('reconcile_spec', {
        description: t('tools.reconcile_spec.description'),
        inputSchema: {
            specId: SpecIdSchema.describe('Spec ID to reconcile'),
            projectId: z.string().max(500).optional().describe('Project ID hash. Prefer projectPath.'),
            projectPath: z
                .string()
                .max(4096)
                .optional()
                .describe('Absolute path to project root. Derives projectId automatically.'),
            autoDetect: z
                .boolean()
                .optional()
                .describe('Auto-detect changes from implementation (default: true)'),
            livingSpec: z
                .boolean()
                .optional()
                .describe('Enable living spec mode: compare acceptance criteria against codebase, auto-mark criteria as met/pending/drift, update the ## Progress section of spec.md (default: false)'),
            changes: z
                .array(z.object({
                section: z.string().max(500),
                originalValue: z.string().max(10_000),
                newValue: z.string().max(10_000),
                reason: z.string().max(10_000),
                approved: z.boolean(),
            }))
                .max(1000)
                .optional()
                .describe('Manual changes to apply'),
        },
    }, safeLicensed('reconcile_spec', async (args) => {
        const pid = resolveProjectId(args);
        if (!pid) {
            return missingProjectIdError;
        }
        return handleReconcileSpec({ ...args, projectId: pid });
    }));
    // 15. learn_pattern
    server.registerTool('learn_pattern', {
        description: t('tools.learn_pattern.description'),
        inputSchema: {
            projectId: z.string().max(500).optional().describe('Project ID hash. Prefer projectPath.'),
            projectPath: z
                .string()
                .max(4096)
                .optional()
                .describe('Absolute path to project root. Derives projectId automatically.'),
            type: z
                .enum(['architecture', 'convention', 'estimation', 'stack', 'quality'])
                .describe('Pattern type: architecture | convention | estimation | stack | quality'),
            pattern: z.string().max(10_000).describe('Pattern description'),
            source: z.string().max(500).optional().describe('Where this pattern was observed'),
        },
    }, safeTracked('learn_pattern', async (args) => {
        const pid = resolveProjectId(args);
        if (!pid) {
            return missingProjectIdError;
        }
        return handleLearn({ ...args, projectId: pid });
    }));
    // 16. audit
    server.registerTool('audit', {
        description: t('tools.audit.description'),
        inputSchema: {
            path: z.string().max(4096).describe('Path to file or directory to audit'),
            projectId: z.string().max(500).optional().describe('Project ID hash. Prefer projectPath.'),
            projectPath: z
                .string()
                .max(4096)
                .optional()
                .describe('Absolute path to project root. Derives projectId automatically.'),
            categories: z
                .array(AuditCategoryEnum)
                .max(100)
                .optional()
                .describe('Audit categories to check'),
            specId: SpecIdSchema.optional().describe('Spec ID to audit against'),
        },
    }, safeLicensed('audit', async (args) => {
        const pid = resolveProjectId(args);
        if (!pid) {
            return missingProjectIdError;
        }
        return handleAudit({ ...args, projectId: pid });
    }));
    // 17. consult_docs
    server.registerTool('consult_docs', {
        description: t('tools.consult_docs.description'),
        inputSchema: {
            topic: z.string().max(500).describe('Topic to search for'),
            projectId: z.string().max(500).optional().describe('Project ID hash. Prefer projectPath.'),
            projectPath: z
                .string()
                .max(4096)
                .optional()
                .describe('Absolute path to project root. Derives projectId automatically.'),
            framework: z
                .string()
                .max(500)
                .optional()
                .describe('Framework to consult docs for (auto-detected if omitted)'),
        },
    }, safeTracked('consult_docs', async (args) => {
        const pid = resolveProjectId(args);
        if (!pid) {
            return missingProjectIdError;
        }
        return handleConsultDocs({ ...args, projectId: pid });
    }));
    // 18. discover_mcps
    server.registerTool('discover_mcps', {
        description: t('tools.discover_mcps.description'),
        inputSchema: {
            configPath: z
                .string()
                .max(4096)
                .optional()
                .describe('Path to MCP config file (auto-detected if omitted)'),
            projectId: z.string().max(500).optional().describe('Project ID'),
        },
    }, safeLicensed('discover_mcps', async (args) => handleDiscoverMcps(args)));
    // 19. suggest_mcps
    server.registerTool('suggest_mcps', {
        description: t('tools.suggest_mcps.description'),
        inputSchema: {
            projectId: z.string().max(500).optional().describe('Project ID hash. Prefer projectPath.'),
            projectPath: z
                .string()
                .max(4096)
                .optional()
                .describe('Absolute path to project root. Derives projectId automatically.'),
            specId: SpecIdSchema.optional().describe('Spec ID for context-specific suggestions'),
        },
    }, safeLicensed('suggest_mcps', async (args) => {
        const pid = resolveProjectId(args);
        if (!pid) {
            return missingProjectIdError;
        }
        return handleSuggestMcps({ ...args, projectId: pid });
    }));
    // 20. suggest_mcp_server — SPEC-132
    server.registerTool('suggest_mcp_server', {
        description: 'Analyze a project and recommend whether it should create an MCP server layer. Returns suggested tools, resources, transport, and estimated effort based on detected app domain (CRM, billing, inventory, healthcare, ecommerce, etc.).',
        annotations: { readOnlyHint: true },
        inputSchema: {
            projectId: z.string().max(500).optional().describe('Project ID hash. Prefer projectPath.'),
            projectPath: z
                .string()
                .max(4096)
                .optional()
                .describe('Absolute path to project root. Derives projectId automatically.'),
        },
    }, safeLicensed('suggest_mcp_server', async (args) => {
        const pid = resolveProjectId(args);
        if (!pid) {
            return missingProjectIdError;
        }
        return handleSuggestMcpServer({ ...args, projectId: pid });
    }));
    // 22. scan_orphan_spec_refs — SPEC-582
    server.registerTool('scan_orphan_spec_refs', {
        description: 'Detect commits referencing SPEC-NNN IDs that have no matching planu/specs/ directory entry. ' +
            'Use mode=report-only (default) to list orphans, mode=strict for CI gate, or mode=create-retroactive to auto-create missing specs.',
        annotations: { readOnlyHint: true },
        inputSchema: ScanOrphanSpecRefsInputSchema,
    }, safeTracked('scan_orphan_spec_refs', async (args) => handleScanOrphanSpecRefs(args)));
    // 21. analyze_spec_dependencies
    server.registerTool('analyze_spec_dependencies', {
        description: 'Analyze spec dependency graph: find critical path, detect circular dependencies, compute execution waves, and generate a Mermaid diagram of the dependency graph.',
        annotations: { readOnlyHint: true },
        inputSchema: {
            projectId: z.string().max(500).optional().describe('Project ID hash. Prefer projectPath.'),
            projectPath: z
                .string()
                .max(4096)
                .optional()
                .describe('Absolute path to project root. Derives projectId automatically.'),
            specIds: z
                .array(z.string().max(500))
                .max(1000)
                .optional()
                .describe('Optional list of spec IDs to analyze (default: all specs)'),
        },
    }, safeTracked('analyze_spec_dependencies', async (args) => {
        const pid = resolveProjectId(args);
        if (!pid) {
            return missingProjectIdError;
        }
        return handleAnalyzeSpecDependencies({ ...args, projectId: pid });
    }));
    // SPEC-746: graph_specs
    registerGraphSpecsTool(server);
    // SPEC-744: audit_specs_drift
    registerAuditSpecsDriftTool(server);
    // SPEC-752: ssr_back_migration — fold legacy split-file specs into unified spec.md
    server.registerTool('ssr_back_migration', {
        description: 'Migrate legacy 2-file format specs into the unified spec.md format. ' +
            'Scans all spec directories under planu/specs/ and inlines legacy technical content as the ' +
            '`## Technical` section of spec.md. Idempotent on already-unified specs. ' +
            'Use dryRun:true (default) to preview changes before applying.',
        annotations: { readOnlyHint: false, destructiveHint: false },
        inputSchema: {
            projectPath: z
                .string()
                .max(4096)
                .optional()
                .describe('Absolute path to project root. Auto-detected from git when omitted.'),
            dryRun: z
                .boolean()
                .optional()
                .describe('When true (default), preview changes without mutating files.'),
            foldProgressMd: z
                .boolean()
                .optional()
                .describe('When true (default), also fold or drop legacy progress content into the ## Progress section of spec.md.'),
            allowDoneSpecs: z
                .boolean()
                .optional()
                .describe('When false (default), done-status specs are skipped (respects SPEC-747 freeze). ' +
                'Set true to migrate done specs (writes backup to planu/backups/ first).'),
        },
    }, safeLicensed('ssr_back_migration', async (args) => handleSsrBackMigration(args)));
}
//# sourceMappingURL=analysis-tools.js.map