/**
 * Hooks Checker - validates hook health (quick check, not full execution)
 */
import * as fs from 'fs';
import * as path from 'path';
import { execSync } from 'child_process';
import { calculateOverallStatus } from '../types.js';
export class HooksChecker {
    constructor() {
        this.category = 'Hooks';
    }
    async check(projectRoot, options) {
        const checks = [];
        // Find hooks in .claude/hooks or plugin hooks
        const hookLocations = this.findHookLocations(projectRoot);
        if (hookLocations.length === 0) {
            checks.push({
                name: 'Hooks',
                status: 'skip',
                message: 'no hooks configured',
            });
            return {
                category: this.category,
                status: 'skip',
                checks,
            };
        }
        // Check each hook location
        for (const location of hookLocations) {
            const hookChecks = await this.checkHooksInLocation(location, options.quick);
            checks.push(...hookChecks);
        }
        // Summary check
        const failedHooks = checks.filter((c) => c.status === 'fail').length;
        const totalHooks = checks.filter((c) => c.status !== 'skip').length;
        if (failedHooks > 0) {
            checks.unshift({
                name: 'Hooks summary',
                status: 'fail',
                message: `${failedHooks}/${totalHooks} hooks failing`,
                fixSuggestion: 'Run: specweave hooks health',
            });
        }
        else if (totalHooks > 0) {
            checks.unshift({
                name: 'Hooks summary',
                status: 'pass',
                message: `${totalHooks}/${totalHooks} hooks healthy`,
            });
        }
        return {
            category: this.category,
            status: calculateOverallStatus(checks),
            checks,
        };
    }
    findHookLocations(projectRoot) {
        const locations = [];
        // Check .claude/hooks
        const claudeHooks = path.join(projectRoot, '.claude', 'hooks');
        if (fs.existsSync(claudeHooks)) {
            locations.push(claudeHooks);
        }
        // Check .specweave hooks (if any)
        const specweaveHooks = path.join(projectRoot, '.specweave', 'hooks');
        if (fs.existsSync(specweaveHooks)) {
            locations.push(specweaveHooks);
        }
        return locations;
    }
    async checkHooksInLocation(location, quickMode) {
        const checks = [];
        try {
            const files = fs.readdirSync(location);
            const hookFiles = files.filter((f) => f.endsWith('.sh') || f.endsWith('.js'));
            for (const hookFile of hookFiles) {
                const hookPath = path.join(location, hookFile);
                const hookName = hookFile.replace(/\.(sh|js)$/, '');
                // Basic syntax check
                const syntaxCheck = this.checkHookSyntax(hookPath, hookFile);
                if (syntaxCheck.status === 'fail') {
                    checks.push(syntaxCheck);
                    continue;
                }
                // Skip execution test in quick mode
                if (quickMode) {
                    checks.push({
                        name: hookName,
                        status: 'skip',
                        message: 'execution skipped (quick mode)',
                    });
                    continue;
                }
                // Quick execution test (with timeout)
                checks.push(await this.testHookExecution(hookPath, hookName));
            }
        }
        catch {
            checks.push({
                name: path.basename(location),
                status: 'fail',
                message: 'could not read hooks directory',
            });
        }
        return checks;
    }
    checkHookSyntax(hookPath, fileName) {
        const hookName = fileName.replace(/\.(sh|js)$/, '');
        try {
            const content = fs.readFileSync(hookPath, 'utf8');
            if (fileName.endsWith('.sh')) {
                // Basic bash syntax check
                if (!content.includes('#!/')) {
                    return {
                        name: hookName,
                        status: 'warn',
                        message: 'missing shebang',
                        fixSuggestion: 'Add #!/bin/bash at the start',
                    };
                }
            }
            return {
                name: `${hookName} syntax`,
                status: 'pass',
                message: 'valid',
            };
        }
        catch {
            return {
                name: `${hookName} syntax`,
                status: 'fail',
                message: 'could not read file',
            };
        }
    }
    async testHookExecution(hookPath, hookName) {
        const start = Date.now();
        try {
            // Dry-run test with minimal input
            execSync(`bash "${hookPath}" --help 2>/dev/null || true`, {
                encoding: 'utf8',
                timeout: 3000,
                stdio: ['pipe', 'pipe', 'pipe'],
                env: {
                    ...process.env,
                    SPECWEAVE_DOCTOR_DRY_RUN: '1',
                },
            });
            return {
                name: `${hookName} execution`,
                status: 'pass',
                message: 'responds',
                durationMs: Date.now() - start,
            };
        }
        catch {
            return {
                name: `${hookName} execution`,
                status: 'warn',
                message: 'execution test failed',
                durationMs: Date.now() - start,
                fixSuggestion: 'Run: specweave hooks health for detailed analysis',
            };
        }
    }
}
//# sourceMappingURL=hooks-checker.js.map