"""Enhanced PR review agent with technical depth for tech leads."""

from __future__ import annotations

import json
import re
from dataclasses import dataclass, field, asdict
from typing import Any, Optional, Dict, List

from emdash.agent.toolkit import AgentToolkit
from emdash.agent.providers import get_provider
from emdash.agent.providers.factory import DEFAULT_MODEL
from emdash.templates import load_template_for_agent
from emdash.utils.logger import log


@dataclass
class TechnicalRisk:
    """A technical risk identified in the PR."""
    
    category: str  # ARCHITECTURE, SECURITY, PERFORMANCE, MAINTAINABILITY
    level: str  # HIGH, MEDIUM, LOW
    description: str
    evidence: str
    mitigation: str
    file_path: Optional[str] = None
    line_number: Optional[int] = None


@dataclass
class CodeQualityMetrics:
    """Code quality analysis results."""
    
    complexity_score: float
    test_coverage_impact: str
    documentation_completeness: float
    security_issues: List[Dict[str, Any]]
    performance_patterns: List[Dict[str, Any]]
    maintainability_score: float


@dataclass
class EnhancedReviewResult:
    """Enhanced review result with technical depth."""
    
    summary: str
    verdict: str
    technical_risks: List[TechnicalRisk]
    quality_metrics: CodeQualityMetrics
    recommendations: List[str]
    code_context: Dict[str, Any]
    confidence_score: float


class EnhancedReviewAgent:
    """Enhanced PR review agent with technical analysis capabilities."""
    
    def __init__(
        self,
        model: str = DEFAULT_MODEL,
        max_files: int = 50,
        max_tokens: int = 50000,
        verbose: bool = True,
    ):
        self.provider = get_provider(model)
        self.toolkit = AgentToolkit(enable_session=False)
        self.model = model
        self.max_files = max_files
        self.max_tokens = max_tokens
        self.verbose = verbose
        
        # Security patterns to check
        self.security_patterns = {
            'sql_injection': [
                r'execute\s*\(\s*["\'].*%s.*["\']',
                r'execute\s*\(\s*.*\+.*',
                r'query\s*\(\s*["\'].*%s.*["\']',
            ],
            'xss_vulnerabilities': [
                r'innerHTML\s*=',
                r'dangerouslySetInnerHTML',
                r'document\.write',
            ],
            'hardcoded_secrets': [
                r'password\s*=\s*["\'][^"\']+["\']',
                r'api_key\s*=\s*["\'][^"\']+["\']',
                r'secret\s*=\s*["\'][^"\']+["\']',
            ],
            'weak_crypto': [
                r'md5\s*\(',
                r'sha1\s*\(',
                r'base64_encode',
            ]
        }
        
        # Performance anti-patterns
        self.performance_patterns = {
            'n_plus_one': [
                r'for.*in.*:\s*.*\.filter\(',
                r'for.*in.*:\s*.*\.get\(',
                r'for.*in.*:\s*.*\.query\(',
            ],
            'inefficient_loops': [
                r'for.*range\(len\(',
                r'while.*True.*break',
            ],
            'memory_leaks': [
                r'global\s+\w+',
                r'static.*=.*\[\]',
            ]
        }

    def generate_enhanced_review(self, pr_number: int) -> EnhancedReviewResult:
        """Generate an enhanced PR review with technical analysis."""
        if self.verbose:
            log.info(f"Generating enhanced review for PR #{pr_number}")
        
        # Fetch PR details
        pr_data = self._fetch_pr_details(pr_number)
        if not pr_data:
            raise ValueError(f"Failed to fetch PR #{pr_number}")
        
        # Parse and analyze changes
        files = self._parse_diff_files(pr_data.get('diff', ''))
        code_context = self._analyze_code_context(files)
        
        # Technical analysis
        impact_analysis = self._analyze_code_impact(files)
        technical_risks = self._assess_technical_risks(pr_data, files, impact_analysis)
        quality_metrics = self._analyze_code_quality(pr_data, files)
        
        # Generate recommendations
        recommendations = self._generate_actionable_recommendations(
            technical_risks, quality_metrics, code_context
        )
        
        # Build enhanced context for LLM
        enhanced_context = self._build_enhanced_context(
            pr_data, technical_risks, quality_metrics, recommendations
        )
        
        # Generate narrative review
        template = self._load_enhanced_template()
        review_content = self._generate_narrative_review(enhanced_context, template)
        
        # Build result
        return EnhancedReviewResult(
            summary=review_content,
            verdict=self._determine_verdict(technical_risks),
            technical_risks=technical_risks,
            quality_metrics=quality_metrics,
            recommendations=recommendations,
            code_context=code_context,
            confidence_score=self._calculate_confidence(technical_risks, quality_metrics)
        )

    def _fetch_pr_details(self, pr_number: int) -> Optional[dict]:
        """Fetch comprehensive PR details."""
        result = self.toolkit.execute(
            "github_pr_details",
            pull_number=pr_number,
            include_diff=True,
            include_comments=True,
            include_reviews=True,
            include_review_comments=True,
        )
        
        if not result.success:
            log.error(f"Failed to fetch PR: {result.error}")
            return None
        
        return result.data

    def _parse_diff_files(self, diff_text: str) -> list[dict]:
        """Parse unified diff into structured file data."""
        if not diff_text:
            return []
        
        files = []
        current_file = None
        current_lines = []
        
        for line in diff_text.splitlines():
            if line.startswith("diff --git"):
                if current_file and current_lines:
                    files.append({
                        "path": current_file,
                        "content": "\n".join(current_lines),
                        "additions": len([l for l in current_lines if l.startswith('+')]),
                        "deletions": len([l for l in current_lines if l.startswith('-')]),
                    })
                current_file = None
                current_lines = []
            elif line.startswith("+++ b/"):
                current_file = line[6:]
            elif current_file:
                current_lines.append(line)
        
        # Don't forget the last file
        if current_file and current_lines:
            files.append({
                "path": current_file,
                "content": "\n".join(current_lines),
                "additions": len([l for l in current_lines if l.startswith('+')]),
                "deletions": len([l for l in current_lines if l.startswith('-')]),
            })
        
        return files[:self.max_files]

    def _analyze_code_context(self, files: list[dict]) -> Dict[str, Any]:
        """Analyze code context using semantic search and dependency analysis."""
        context = {
            'similar_patterns': {},
            'dependencies': {},
            'security_issues': {},
            'performance_issues': {},
            'architectural_impact': {}
        }
        
        for file_info in files:
            file_path = file_info['path']
            
            # Skip non-code files
            if not any(file_path.endswith(ext) for ext in ['.py', '.js', '.ts', '.jsx', '.tsx']):
                continue
            
            try:
                # Find similar patterns in codebase
                similar_result = self.toolkit.execute(
                    "semantic_search",
                    query=f"code patterns in {file_path}",
                    entity_types=["Function", "Class"],
                    limit=5
                )
                if similar_result.success:
                    context['similar_patterns'][file_path] = similar_result.data.get('results', [])
                
                # Analyze dependencies
                dep_result = self.toolkit.execute(
                    "get_file_dependencies",
                    file_path=file_path
                )
                if dep_result.success:
                    context['dependencies'][file_path] = dep_result.data
                
                # Security analysis
                security_issues = self._analyze_security_issues(file_info['content'])
                if security_issues:
                    context['security_issues'][file_path] = security_issues
                
                # Performance analysis
                perf_issues = self._analyze_performance_issues(file_info['content'])
                if perf_issues:
                    context['performance_issues'][file_path] = perf_issues
                    
            except Exception as e:
                log.warning(f"Failed to analyze context for {file_path}: {e}")
        
        return context

    def _analyze_security_issues(self, content: str) -> List[Dict[str, Any]]:
        """Analyze code for security vulnerabilities."""
        issues = []
        
        for issue_type, patterns in self.security_patterns.items():
            for pattern in patterns:
                matches = re.findall(pattern, content, re.IGNORECASE)
                if matches:
                    issues.append({
                        'type': issue_type,
                        'severity': 'HIGH' if issue_type in ['sql_injection', 'xss_vulnerabilities'] else 'MEDIUM',
                        'pattern': pattern,
                        'matches': matches[:3],  # Limit matches
                        'description': self._get_security_description(issue_type)
                    })
        
        return issues

    def _analyze_performance_issues(self, content: str) -> List[Dict[str, Any]]:
        """Analyze code for performance anti-patterns."""
        issues = []
        
        for issue_type, patterns in self.performance_patterns.items():
            for pattern in patterns:
                matches = re.findall(pattern, content, re.IGNORECASE)
                if matches:
                    issues.append({
                        'type': issue_type,
                        'severity': 'HIGH' if issue_type == 'n_plus_one' else 'MEDIUM',
                        'pattern': pattern,
                        'matches': matches[:3],
                        'description': self._get_performance_description(issue_type)
                    })
        
        return issues

    def _analyze_code_impact(self, files: list[dict]) -> Dict[str, Any]:
        """Analyze the impact of code changes."""
        impact_analysis = {
            'affected_services': [],
            'api_changes': [],
            'database_changes': [],
            'dependency_changes': [],
            'configuration_changes': []
        }
        
        for file_info in files:
            file_path = file_info['path']
            content = file_info['content']
            
            # Check for API changes
            if self._is_api_file(file_path):
                api_changes = self._extract_api_changes(content)
                if api_changes:
                    impact_analysis['api_changes'].extend(api_changes)
            
            # Check for database changes
            if self._is_database_file(file_path):
                db_changes = self._extract_database_changes(content)
                if db_changes:
                    impact_analysis['database_changes'].extend(db_changes)
            
            # Check for dependency changes
            if 'package.json' in file_path or 'requirements.txt' in file_path:
                dep_changes = self._extract_dependency_changes(content)
                if dep_changes:
                    impact_analysis['dependency_changes'].extend(dep_changes)
            
            # Check for configuration changes
            if self._is_config_file(file_path):
                config_changes = self._extract_config_changes(content)
                if config_changes:
                    impact_analysis['configuration_changes'].extend(config_changes)
        
        return impact_analysis

    def _assess_technical_risks(self, pr_data: dict, files: list[dict], 
                               impact_analysis: dict) -> List[TechnicalRisk]:
        """Assess technical risks for tech lead review."""
        risks = []
        pr = pr_data.get('pr', {})
        
        # Architecture risks
        if self._has_major_architecture_changes(files):
            risks.append(TechnicalRisk(
                category='ARCHITECTURE',
                level='HIGH',
                description='Significant architectural changes detected',
                evidence=self._get_architecture_evidence(files),
                mitigation='Request architecture review from senior engineer',
                file_path=None,
                line_number=None
            ))
        
        # Security risks
        security_issues = self._extract_security_issues_from_impact(impact_analysis)
        if security_issues:
            risks.append(TechnicalRisk(
                category='SECURITY',
                level='HIGH',
                description=f'{len(security_issues)} security issues detected',
                evidence=json.dumps(security_issues[:5], indent=2),
                mitigation='Address security issues before merge',
                file_path=None,
                line_number=None
            ))
        
        # Performance risks
        if self._has_performance_implications(files):
            risks.append(TechnicalRisk(
                category='PERFORMANCE',
                level='MEDIUM',
                description='Potential performance impact detected',
                evidence=self._get_performance_evidence(files),
                mitigation='Add performance benchmarks and test with realistic data',
                file_path=None,
                line_number=None
            ))
        
        # Maintainability risks
        if self._has_maintainability_issues(files):
            risks.append(TechnicalRisk(
                category='MAINTAINABILITY',
                level='MEDIUM',
                description='Code complexity or technical debt introduced',
                evidence=self._get_maintainability_evidence(files),
                mitigation='Refactor complex sections and add documentation',
                file_path=None,
                line_number=None
            ))
        
        # Breaking change risks
        if impact_analysis.get('api_changes'):
            risks.append(TechnicalRisk(
                category='API_COMPATIBILITY',
                level='HIGH',
                description='API contract changes detected',
                evidence=json.dumps(impact_analysis['api_changes'][:3], indent=2),
                mitigation='Verify backward compatibility and update API documentation',
                file_path=None,
                line_number=None
            ))
        
        # Database migration risks
        if impact_analysis.get('database_changes'):
            risks.append(TechnicalRisk(
                category='DATABASE',
                level='HIGH',
                description='Database schema changes detected',
                evidence=json.dumps(impact_analysis['database_changes'][:3], indent=2),
                mitigation='Review migration safety and test with production-like data',
                file_path=None,
                line_number=None
            ))
        
        return risks

    def _analyze_code_quality(self, pr_data: dict, files: list[dict]) -> CodeQualityMetrics:
        """Perform detailed code quality analysis."""
        total_complexity = 0
        total_lines = 0
        security_issues = []
        performance_issues = []
        
        for file_info in files:
            content = file_info['content']
            lines = content.split('\n')
            total_lines += len(lines)
            
            # Calculate complexity (simplified)
            complexity = self._calculate_complexity(content)
            total_complexity += complexity
            
            # Collect security issues
            file_security = self._analyze_security_issues(content)
            security_issues.extend(file_security)
            
            # Collect performance issues
            file_performance = self._analyze_performance_issues(content)
            performance_issues.extend(file_performance)
        
        avg_complexity = total_complexity / len(files) if files else 0
        
        # Estimate test coverage impact
        test_coverage = self._estimate_test_coverage_impact(files)
        
        # Check documentation completeness
        doc_completeness = self._check_documentation_completeness(files)
        
        # Calculate maintainability score
        maintainability = self._calculate_maintainability_score(
            avg_complexity, len(security_issues), doc_completeness
        )
        
        return CodeQualityMetrics(
            complexity_score=avg_complexity,
            test_coverage_impact=test_coverage,
            documentation_completeness=doc_completeness,
            security_issues=security_issues,
            performance_patterns=performance_issues,
            maintainability_score=maintainability
        )

    def _generate_actionable_recommendations(self, technical_risks: List[TechnicalRisk],
                                           quality_metrics: CodeQualityMetrics,
                                           code_context: Dict[str, Any]) -> List[str]:
        """Generate specific actionable recommendations for tech leads."""
        recommendations = []
        
        # Prioritize by risk level
        high_risk_items = [r for r in technical_risks if r.level == 'HIGH']
        medium_risk_items = [r for r in technical_risks if r.level == 'MEDIUM']
        
        # High priority recommendations
        for risk in high_risk_items:
            recommendations.append(
                f"🚨 **BLOCKER**: {risk.description}\n"
                f"   Evidence: {risk.evidence[:200]}...\n"
                f"   Action: {risk.mitigation}"
            )
        
        # Medium priority recommendations
        for risk in medium_risk_items:
            recommendations.append(
                f"⚠️ **CONSIDER**: {risk.description}\n"
                f"   Action: {risk.mitigation}"
            )
        
        # Code quality recommendations
        if quality_metrics.complexity_score > 10:
            recommendations.append(
                "📊 **COMPLEXITY**: High cyclomatic complexity detected\n"
                "   Action: Refactor complex functions into smaller, testable units"
            )
        
        if quality_metrics.security_issues:
            recommendations.append(
                f"🔒 **SECURITY**: {len(quality_metrics.security_issues)} security issues found\n"
                "   Action: Address SQL injection, XSS, and hardcoded secrets before merge"
            )
        
        if quality_metrics.performance_patterns:
            recommendations.append(
                f"⚡ **PERFORMANCE**: {len(quality_metrics.performance_patterns)} performance issues detected\n"
                "   Action: Optimize N+1 queries and inefficient loops"
            )
        
        if quality_metrics.documentation_completeness < 70:
            recommendations.append(
                f"📝 **DOCUMENTATION**: Only {quality_metrics.documentation_completeness:.1f}% documented\n"
                "   Action: Add docstrings and comments for complex logic"
            )
        
        # Context-based recommendations
        if code_context.get('dependencies'):
            recommendations.append(
                "🔗 **DEPENDENCIES**: Review dependency changes for security and compatibility"
            )
        
        if code_context.get('similar_patterns'):
            recommendations.append(
                "🎯 **CONSISTENCY**: Ensure changes follow existing code patterns in the codebase"
            )
        
        return recommendations

    def _build_enhanced_context(self, pr_data: dict, technical_risks: List[TechnicalRisk],
                              quality_metrics: CodeQualityMetrics,
                              recommendations: List[str]) -> str:
        """Build enhanced context for the LLM review."""
        pr = pr_data.get('pr', {})
        
        context_parts = [
            f"# Enhanced PR Review: #{pr.get('number')} - {pr.get('title')}",
            f"\n**Author:** {pr.get('user', {}).get('login', 'unknown')}",
            f"**Changes:** +{pr.get('additions', 0)} / -{pr.get('deletions', 0)} lines",
            f"**Files Changed:** {len(pr_data.get('diff', '').split('diff --git')) - 1}",
        ]
        
        # Technical risks summary
        if technical_risks:
            context_parts.append("\n## Technical Risk Assessment")
            high_risks = [r for r in technical_risks if r.level == 'HIGH']
            medium_risks = [r for r in technical_risks if r.level == 'MEDIUM']
            
            if high_risks:
                context_parts.append(f"🚨 **HIGH RISK**: {len(high_risks)} critical issues")
            if medium_risks:
                context_parts.append(f"⚠️ **MEDIUM RISK**: {len(medium_risks)} issues requiring attention")
        
        # Quality metrics
        context_parts.append("\n## Code Quality Analysis")
        context_parts.append(f"- **Complexity Score**: {quality_metrics.complexity_score:.1f}/10")
        context_parts.append(f"- **Documentation**: {quality_metrics.documentation_completeness:.1f}%")
        context_parts.append(f"- **Security Issues**: {len(quality_metrics.security_issues)}")
        context_parts.append(f"- **Performance Issues**: {len(quality_metrics.performance_patterns)}")
        context_parts.append(f"- **Maintainability**: {quality_metrics.maintainability_score:.1f}/10")
        
        # Recommendations
        if recommendations:
            context_parts.append("\n## Priority Recommendations")
            for i, rec in enumerate(recommendations[:5], 1):  # Top 5 recommendations
                context_parts.append(f"{i}. {rec}")
        
        # PR description
        body = pr.get("body")
        if body:
            context_parts.append(f"\n## PR Description\n{body[:1000]}")
        
        return "\n".join(context_parts)

    def _generate_narrative_review(self, context: str, template: str) -> str:
        """Generate the final narrative review."""
        messages = [
            {"role": "system", "content": template},
            {"role": "user", "content": context},
        ]
        
        response = self.provider.chat(messages)
        return response.content or ""

    def _load_enhanced_template(self) -> str:
        """Load enhanced review template for tech leads."""
        try:
            return load_template_for_agent("pr-review-enhanced")
        except FileNotFoundError:
            # Fallback to basic template with enhancements
            return self._build_enhanced_template()

    def _build_enhanced_template(self) -> str:
        """Build enhanced template for tech leads."""
        return """# PR Review - Technical Analysis

You are a senior engineering lead conducting a thorough technical review of this pull request. Your analysis should be comprehensive, actionable, and focused on technical excellence.

## Review Structure

### A) Executive Summary
- Decision: [APPROVE/REQUEST_CHANGES/COMMENT]
- Risk Level: [LOW/MEDIUM/HIGH]
- Key Concerns: [Top 3 technical issues]

### B) Technical Risk Assessment
Analyze and report on:
1. **Architecture Impact**: Breaking changes, design patterns, scalability
2. **Security Vulnerabilities**: Input validation, authentication, data exposure
3. **Performance Implications**: Algorithmic complexity, resource usage, bottlenecks
4. **Maintainability**: Code complexity, technical debt, documentation
5. **Testing Coverage**: Unit tests, integration tests, edge cases

### C) Code Quality Analysis
Provide specific metrics:
- Cyclomatic complexity scores
- Security vulnerability count and severity
- Performance anti-patterns identified
- Documentation completeness percentage
- Test coverage impact assessment

### D) Detailed Technical Review
For each changed file:
1. **Code Correctness**: Logic errors, edge cases, error handling
2. **Best Practices**: Language-specific patterns, conventions
3. **Performance**: Efficiency concerns, optimization opportunities
4. **Security**: Vulnerability assessment, input validation
5. **Maintainability**: Readability, modularity, documentation

### E) Actionable Recommendations
Provide specific, prioritized actions:
1. **Blockers**: Issues that must be resolved before merge
2. **Improvements**: Suggestions for better code quality
3. **Follow-ups**: Items for future consideration

### F) Verification Checklist
What the reviewer should specifically check:
- [ ] Security vulnerabilities addressed
- [ ] Performance implications tested
- [ ] Breaking changes documented
- [ ] Tests cover new functionality
- [ ] Documentation updated

## Review Guidelines

1. **Be Technical**: Focus on code quality, architecture, and engineering best practices
2. **Provide Evidence**: Include specific code snippets and line numbers
3. **Prioritize Risks**: Clearly distinguish between blockers and suggestions
4. **Suggest Solutions**: Don't just identify problems, propose fixes
5. **Consider Context**: Analyze impact on the broader system and team

## Output Requirements

- Use clear, professional language
- Include specific code examples with line numbers
- Provide actionable recommendations with priority levels
- Focus on technical excellence over politeness
- Be thorough but concise in your analysis

Begin your review with the provided technical context and risk assessment data."""

    def _determine_verdict(self, technical_risks: List[TechnicalRisk]) -> str:
        """Determine review verdict based on technical risks."""
        high_risk_count = len([r for r in technical_risks if r.level == 'HIGH'])
        
        if high_risk_count > 0:
            return 'REQUEST_CHANGES'
        elif len(technical_risks) > 3:
            return 'COMMENT'
        else:
            return 'APPROVE'

    def _calculate_confidence(self, technical_risks: List[TechnicalRisk],
                            quality_metrics: CodeQualityMetrics) -> float:
        """Calculate confidence score based on analysis completeness."""
        base_confidence = 0.8
        
        # Reduce confidence for high-risk items
        high_risk_penalty = len([r for r in technical_risks if r.level == 'HIGH']) * 0.1
        
        # Reduce confidence for poor quality metrics
        quality_penalty = 0
        if quality_metrics.complexity_score > 15:
            quality_penalty += 0.1
        if quality_metrics.security_issues:
            quality_penalty += 0.1
        if quality_metrics.documentation_completeness < 50:
            quality_penalty += 0.05
        
        return max(0.1, base_confidence - high_risk_penalty - quality_penalty)

    # Helper methods for analysis
    def _get_security_description(self, issue_type: str) -> str:
        """Get description for security issue type."""
        descriptions = {
            'sql_injection': 'Potential SQL injection vulnerability',
            'xss_vulnerabilities': 'Cross-site scripting vulnerability',
            'hardcoded_secrets': 'Hardcoded credentials or secrets',
            'weak_crypto': 'Weak cryptographic algorithms'
        }
        return descriptions.get(issue_type, 'Security vulnerability')

    def _get_performance_description(self, issue_type: str) -> str:
        """Get description for performance issue type."""
        descriptions = {
            'n_plus_one': 'N+1 query pattern detected',
            'inefficient_loops': 'Inefficient loop patterns',
            'memory_leaks': 'Potential memory leak'
        }
        return descriptions.get(issue_type, 'Performance issue')

    def _has_major_architecture_changes(self, files: list[dict]) -> bool:
        """Check for major architecture changes."""
        architecture_files = ['architecture.md', 'design.md', 'README.md', 
                            'docker-compose.yml', 'kubernetes/', 'terraform/']
        
        for file_info in files:
            file_path = file_info['path']
            if any(arch_file in file_path for arch_file in architecture_files):
                return True
        
        return False

    def _get_architecture_evidence(self, files: list[dict]) -> str:
        """Get evidence of architecture changes."""
        evidence = []
        for file_info in files:
            file_path = file_info['path']
            if 'architecture' in file_path.lower() or 'design' in file_path.lower():
                evidence.append(f"Modified: {file_path}")
        
        return "\n".join(evidence) if evidence else "Architecture-related changes detected"

    def _has_performance_implications(self, files: list[dict]) -> bool:
        """Check for performance implications."""
        performance_files = ['queries.py', 'models.py', 'views.py', 'services.py']
        
        for file_info in files:
            file_path = file_info['path']
            if any(perf_file in file_path for perf_file in performance_files):
                return True
        
        return False

    def _get_performance_evidence(self, files: list[dict]) -> str:
        """Get evidence of performance implications."""
        return "Database queries or service logic modified"

    def _has_maintainability_issues(self, files: list[dict]) -> bool:
        """Check for maintainability issues."""
        # Simple heuristic - large files or many changes
        for file_info in files:
            if len(file_info['content'].split('\n')) > 500:
                return True
        
        return False

    def _get_maintainability_evidence(self, files: list[dict]) -> str:
        """Get evidence of maintainability issues."""
        large_files = []
        for file_info in files:
            line_count = len(file_info['content'].split('\n'))
            if line_count > 500:
                large_files.append(f"{file_info['path']}: {line_count} lines")
        
        return "\n".join(large_files) if large_files else "Large changes detected"

    def _is_api_file(self, file_path: str) -> bool:
        """Check if file is API-related."""
        api_indicators = ['api/', 'views.py', 'controllers/', 'routes.py', 'endpoints/']
        return any(indicator in file_path for indicator in api_indicators)

    def _extract_api_changes(self, content: str) -> List[Dict[str, Any]]:
        """Extract API changes from content."""
        api_changes = []
        
        # Look for route changes
        route_patterns = [
            r'@app\.route\s*\(\s*["\']([^"\']+)["\']',
            r'router\.(get|post|put|delete)\s*\(\s*["\']([^"\']+)["\']',
            r'@.*Mapping\s*\(\s*["\']([^"\']+)["\']'
        ]
        
        for pattern in route_patterns:
            matches = re.findall(pattern, content)
            for match in matches:
                route = match if isinstance(match, str) else match[1] if len(match) > 1 else match[0]
                api_changes.append({
                    'type': 'route_change',
                    'route': route,
                    'impact': 'potential_breaking_change'
                })
        
        return api_changes

    def _is_database_file(self, file_path: str) -> bool:
        """Check if file is database-related."""
        db_indicators = ['models.py', 'migrations/', 'schema.sql', 'database/']
        return any(indicator in file_path for indicator in db_indicators)

    def _extract_database_changes(self, content: str) -> List[Dict[str, Any]]:
        """Extract database changes from content."""
        db_changes = []
        
        # Look for migration patterns
        migration_patterns = [
            r'alter_table\s*\(\s*["\']([^"\']+)["\']',
            r'drop_table\s*\(\s*["\']([^"\']+)["\']',
            r'add_column\s*\(\s*["\']([^"\']+)["\']',
            r'rename_column\s*\(\s*["\']([^"\']+)["\']'
        ]
        
        for pattern in migration_patterns:
            matches = re.findall(pattern, content, re.IGNORECASE)
            for match in matches:
                db_changes.append({
                    'type': 'schema_change',
                    'table': match,
                    'impact': 'requires_migration'
                })
        
        return db_changes

    def _is_config_file(self, file_path: str) -> bool:
        """Check if file is configuration-related."""
        config_indicators = ['config/', 'settings.py', '.env', 'docker-compose', 'kubernetes/']
        return any(indicator in file_path for indicator in config_indicators)

    def _extract_config_changes(self, content: str) -> List[Dict[str, Any]]:
        """Extract configuration changes from content."""
        config_changes = []
        
        # Look for environment variable changes
        env_patterns = [
            r'os\.environ\.get\s*\(\s*["\']([^"\']+)["\']',
            r'config\s*\[\s*["\']([^"\']+)["\']',
            r'SETTINGS\s*\[\s*["\']([^"\']+)["\']'
        ]
        
        for pattern in env_patterns:
            matches = re.findall(pattern, content)
            for match in matches:
                config_changes.append({
                    'type': 'config_change',
                    'key': match,
                    'impact': 'requires_deployment_update'
                })
        
        return config_changes

    def _extract_dependency_changes(self, content: str) -> List[Dict[str, Any]]:
        """Extract dependency changes from content."""
        dep_changes = []
        
        # Look for version changes
        version_patterns = [
            r'(["\'][^"\']+["\'])\s*==?\s*([^\s,]+)',
            r'(["\'][^"\']+["\'])\s*>=?\s*([^\s,]+)',
            r'(["\'][^"\']+["\'])\s*<=\s*([^\s,]+)'
        ]
        
        for pattern in version_patterns:
            matches = re.findall(pattern, content)
            for match in matches:
                if len(match) == 2:
                    dep_changes.append({
                        'type': 'version_change',
                        'package': match[0].strip('"\''),
                        'version': match[1],
                        'impact': 'dependency_update'
                    })
        
        return dep_changes

    def _extract_security_issues_from_impact(self, impact_analysis: dict) -> List[Dict[str, Any]]:
        """Extract security issues from impact analysis."""
        security_issues = []
        
        for file_path, issues in impact_analysis.get('security_issues', {}).items():
            security_issues.extend(issues)
        
        return security_issues

    def _calculate_complexity(self, content: str) -> float:
        """Calculate cyclomatic complexity (simplified)."""
        complexity_indicators = [
            r'\bif\b', r'\belse\b', r'\belif\b', r'\bwhile\b', 
            r'\bfor\b', r'\bcase\b', r'\bcatch\b', r'\band\b', r'\bor\b'
        ]
        
        total_complexity = 0
        for pattern in complexity_indicators:
            matches = re.findall(pattern, content, re.IGNORECASE)
            total_complexity += len(matches)
        
        # Normalize by file size
        lines = len(content.split('\n'))
        return total_complexity / max(1, lines / 100)  # Complexity per 100 lines

    def _estimate_test_coverage_impact(self, files: list[dict]) -> str:
        """Estimate test coverage impact."""
        code_files = [f for f in files if any(f['path'].endswith(ext) for ext in ['.py', '.js', '.ts'])]
        
        if not code_files:
            return "No code files detected"
        
        # Simple heuristic: check for test files
        test_files = [f for f in files if 'test' in f['path'].lower()]
        
        if len(test_files) < len(code_files) * 0.5:
            return "Low test coverage - consider adding tests"
        elif len(test_files) < len(code_files):
            return "Moderate test coverage - add tests for new functionality"
        else:
            return "Good test coverage - verify tests cover edge cases"

    def _check_documentation_completeness(self, files: list[dict]) -> float:
        """Check documentation completeness percentage."""
        documented_functions = 0
        total_functions = 0
        
        for file_info in files:
            content = file_info['content']
            
            # Count function definitions and docstrings (simplified)
            function_pattern = r'def\s+\w+\s*\('
            docstring_pattern = r'"""[\s\S]*?"""'
            
            functions = re.findall(function_pattern, content)
            docstrings = re.findall(docstring_pattern, content)
            
            total_functions += len(functions)
            documented_functions += min(len(functions), len(docstrings))
        
        if total_functions == 0:
            return 100.0
        
        return (documented_functions / total_functions) * 100

    def _calculate_maintainability_score(self, complexity: float, security_issues: int, 
                                       documentation: float) -> float:
        """Calculate maintainability score (0-10)."""
        # Start with base score
        score = 10.0
        
        # Penalize high complexity
        if complexity > 20:
            score -= 3.0
        elif complexity > 10:
            score -= 2.0
        elif complexity > 5:
            score -= 1.0
        
        # Penalize security issues
        score -= min(security_issues * 0.5, 3.0)
        
        # Penalize poor documentation
        if documentation < 50:
            score -= 2.0
        elif documentation < 70:
            score -= 1.0
        
        return max(0.0, score)