import { promises as fs } from 'fs';
import path from 'path';
export class CodeAnalyzer {
    async analyzeFile(filePath) {
        const content = await fs.readFile(filePath, 'utf-8');
        const language = this.detectLanguage(filePath);
        const analysis = {
            file: filePath,
            language,
            metrics: this.calculateMetrics(content),
            dependencies: this.extractDependencies(content, language),
            exports: this.extractExports(content, language),
            imports: this.extractImports(content, language),
            functions: this.extractFunctions(content, language),
            classes: this.extractClasses(content, language),
            complexity: this.analyzeComplexity(content, language),
        };
        return analysis;
    }
    detectLanguage(filePath) {
        const ext = path.extname(filePath).toLowerCase();
        const languageMap = {
            '.ts': 'typescript',
            '.tsx': 'typescript',
            '.js': 'javascript',
            '.jsx': 'javascript',
            '.py': 'python',
            '.rs': 'rust',
            '.go': 'go',
            '.java': 'java',
            '.cpp': 'cpp',
            '.c': 'c',
        };
        return languageMap[ext] || 'unknown';
    }
    calculateMetrics(content) {
        const lines = content.split('\n');
        let loc = 0;
        let comments = 0;
        let blanks = 0;
        for (const line of lines) {
            const trimmed = line.trim();
            if (trimmed === '') {
                blanks++;
            }
            else if (this.isComment(trimmed)) {
                comments++;
            }
            else {
                loc++;
            }
        }
        return {
            lines: lines.length,
            loc,
            comments,
            blanks,
            complexity: this.calculateCyclomaticComplexity(content),
        };
    }
    isComment(line) {
        const commentPatterns = [
            /^\s*\/\//, // JS/TS single line
            /^\s*\/\*/, // JS/TS multi line start
            /^\s*\*/, // JS/TS multi line continuation
            /^\s*#/, // Python, Shell
            /^\s*--/, // SQL, Haskell
        ];
        return commentPatterns.some(pattern => pattern.test(line));
    }
    calculateCyclomaticComplexity(content) {
        // Simplified cyclomatic complexity calculation
        const complexityPatterns = [
            /\bif\b/g,
            /\belse\s+if\b/g,
            /\bwhile\b/g,
            /\bfor\b/g,
            /\bcase\b/g,
            /\bcatch\b/g,
            /\?\s*:/g, // Ternary operator
            /&&/g, // Logical AND
            /\|\|/g, // Logical OR
        ];
        let complexity = 1; // Base complexity
        for (const pattern of complexityPatterns) {
            const matches = content.match(pattern);
            if (matches) {
                complexity += matches.length;
            }
        }
        return complexity;
    }
    extractDependencies(content, language) {
        const dependencies = [];
        if (language === 'typescript' || language === 'javascript') {
            // Extract import statements
            const importRegex = /import\s+.*\s+from\s+['"]([^'"]+)['"]/g;
            const requireRegex = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
            let match;
            while ((match = importRegex.exec(content)) !== null) {
                dependencies.push(match[1]);
            }
            while ((match = requireRegex.exec(content)) !== null) {
                dependencies.push(match[1]);
            }
        }
        return [...new Set(dependencies)];
    }
    extractImports(content, language) {
        if (language === 'typescript' || language === 'javascript') {
            const imports = [];
            const regex = /import\s+(?:{([^}]+)}|(\w+)|(\*\s+as\s+\w+))\s+from\s+['"]([^'"]+)['"]/g;
            let match;
            while ((match = regex.exec(content)) !== null) {
                if (match[1]) {
                    // Named imports
                    imports.push(...match[1].split(',').map(s => s.trim()));
                }
                else if (match[2]) {
                    // Default import
                    imports.push(match[2]);
                }
                else if (match[3]) {
                    // Namespace import
                    imports.push(match[3]);
                }
            }
            return imports;
        }
        return [];
    }
    extractExports(content, language) {
        if (language === 'typescript' || language === 'javascript') {
            const exports = [];
            // Named exports
            const namedExportRegex = /export\s+(?:const|let|var|function|class)\s+(\w+)/g;
            let match;
            while ((match = namedExportRegex.exec(content)) !== null) {
                exports.push(match[1]);
            }
            // Export statements
            const exportStmtRegex = /export\s+{([^}]+)}/g;
            while ((match = exportStmtRegex.exec(content)) !== null) {
                exports.push(...match[1].split(',').map(s => s.trim().split(/\s+as\s+/)[0]));
            }
            return [...new Set(exports)];
        }
        return [];
    }
    extractFunctions(content, language) {
        const functions = [];
        if (language === 'typescript' || language === 'javascript') {
            // Function declarations
            const funcRegex = /(?:async\s+)?function\s+(\w+)\s*\(([^)]*)\)/g;
            const arrowRegex = /(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?\(([^)]*)\)\s*=>/g;
            const lines = content.split('\n');
            let match;
            while ((match = funcRegex.exec(content)) !== null) {
                const lineNumber = content.substring(0, match.index).split('\n').length;
                functions.push({
                    name: match[1],
                    line: lineNumber,
                    params: match[2].split(',').map(p => p.trim()).filter(p => p),
                    complexity: 1, // Would need proper AST parsing for accurate complexity
                    length: this.getFunctionLength(content, match.index),
                });
            }
            while ((match = arrowRegex.exec(content)) !== null) {
                const lineNumber = content.substring(0, match.index).split('\n').length;
                functions.push({
                    name: match[1],
                    line: lineNumber,
                    params: match[2].split(',').map(p => p.trim()).filter(p => p),
                    complexity: 1,
                    length: this.getFunctionLength(content, match.index),
                });
            }
        }
        return functions;
    }
    extractClasses(content, language) {
        const classes = [];
        if (language === 'typescript' || language === 'javascript') {
            const classRegex = /class\s+(\w+)(?:\s+extends\s+(\w+))?(?:\s+implements\s+([^{]+))?\s*{/g;
            let match;
            while ((match = classRegex.exec(content)) !== null) {
                const lineNumber = content.substring(0, match.index).split('\n').length;
                classes.push({
                    name: match[1],
                    line: lineNumber,
                    extends: match[2],
                    implements: match[3]?.split(',').map(i => i.trim()),
                    methods: [], // Would need proper AST parsing
                    properties: [],
                });
            }
        }
        return classes;
    }
    getFunctionLength(content, startIndex) {
        // Simplified function length calculation
        // In reality, would need proper AST parsing
        const afterFunction = content.substring(startIndex);
        const lines = afterFunction.split('\n');
        let braceCount = 0;
        let lineCount = 0;
        for (const line of lines) {
            lineCount++;
            braceCount += (line.match(/{/g) || []).length;
            braceCount -= (line.match(/}/g) || []).length;
            if (braceCount === 0 && lineCount > 1) {
                return lineCount;
            }
        }
        return lineCount;
    }
    analyzeComplexity(content, language) {
        const complexity = this.calculateCyclomaticComplexity(content);
        const loc = content.split('\n').filter(line => line.trim() && !this.isComment(line.trim())).length;
        // Simplified maintainability index
        const maintainabilityIndex = Math.max(0, Math.min(100, 171 - 5.2 * Math.log(complexity) - 0.23 * complexity - 16.2 * Math.log(loc)));
        const suggestions = [];
        if (complexity > 10) {
            suggestions.push({
                type: 'refactor',
                description: 'Consider breaking this code into smaller functions',
                severity: complexity > 20 ? 'high' : 'medium',
            });
        }
        if (loc > 200) {
            suggestions.push({
                type: 'split',
                description: 'This file is getting large. Consider splitting it into multiple modules',
                severity: loc > 500 ? 'high' : 'medium',
            });
        }
        if (maintainabilityIndex < 50) {
            suggestions.push({
                type: 'simplify',
                description: 'Code maintainability is low. Consider refactoring for clarity',
                severity: 'high',
            });
        }
        return {
            cyclomatic: complexity,
            cognitive: complexity * 1.2, // Simplified cognitive complexity
            maintainabilityIndex,
            suggestions,
        };
    }
}
//# sourceMappingURL=analyzer.js.map