"""
Code Reviewer Utility for Code Assistant Bot
Author: RSK World (https://rskworld.in)
Founder: Molla Samser
Designer & Tester: Rima Khatun
Contact: help@rskworld.in, +91 93305 39277
Year: 2026
"""

import re
import ast
from typing import Dict, List, Any, Optional

class CodeReviewer:
    """
    Utility class for code review and suggestions
    """
    
    def __init__(self):
        self.review_rules = {
            'python': self._review_python,
            'javascript': self._review_javascript,
            'typescript': self._review_javascript,
            'java': self._review_java,
            'cpp': self._review_cpp,
            'c': self._review_cpp
        }
    
    def review_code(self, code: str, language: str) -> Dict[str, Any]:
        """
        Review code and provide suggestions
        """
        try:
            review_function = self.review_rules.get(language, self._review_generic)
            return review_function(code, language)
        except Exception as e:
            return {
                'success': False,
                'error': f'Code review failed: {str(e)}',
                'issues': [],
                'suggestions': []
            }
    
    def _review_python(self, code: str, language: str) -> Dict[str, Any]:
        """Review Python code"""
        issues = []
        suggestions = []
        
        try:
            # Parse code
            tree = ast.parse(code)
            lines = code.split('\n')
            
            # Check for PEP 8 violations
            for i, line in enumerate(lines, 1):
                # Line length
                if len(line) > 79:
                    issues.append({
                        'type': 'style',
                        'severity': 'low',
                        'line': i,
                        'message': f'Line {i} exceeds 79 characters (PEP 8)',
                        'suggestion': 'Break long lines into multiple lines'
                    })
                
                # Trailing whitespace
                if line.rstrip() != line:
                    issues.append({
                        'type': 'style',
                        'severity': 'low',
                        'line': i,
                        'message': f'Line {i} has trailing whitespace',
                        'suggestion': 'Remove trailing whitespace'
                    })
            
            # Check for missing docstrings
            for node in ast.walk(tree):
                if isinstance(node, ast.FunctionDef):
                    if not ast.get_docstring(node):
                        suggestions.append({
                            'type': 'documentation',
                            'severity': 'medium',
                            'line': node.lineno,
                            'message': f'Function "{node.name}" is missing a docstring',
                            'suggestion': 'Add a docstring describing the function'
                        })
                
                elif isinstance(node, ast.ClassDef):
                    if not ast.get_docstring(node):
                        suggestions.append({
                            'type': 'documentation',
                            'severity': 'medium',
                            'line': node.lineno,
                            'message': f'Class "{node.name}" is missing a docstring',
                            'suggestion': 'Add a docstring describing the class'
                        })
            
            # Check for bare except
            for node in ast.walk(tree):
                if isinstance(node, ast.ExceptHandler):
                    if node.type is None:
                        issues.append({
                            'type': 'error_handling',
                            'severity': 'high',
                            'line': node.lineno,
                            'message': 'Bare except clause found',
                            'suggestion': 'Specify exception types instead of bare except'
                        })
            
            # Check for unused imports (basic)
            imports = []
            for node in ast.walk(tree):
                if isinstance(node, ast.Import):
                    for alias in node.names:
                        imports.append(alias.name)
                elif isinstance(node, ast.ImportFrom):
                    if node.module:
                        imports.append(node.module)
            
            # Check for potential bugs
            code_str = code.lower()
            if 'eval(' in code_str:
                issues.append({
                    'type': 'security',
                    'severity': 'critical',
                    'line': 0,
                    'message': 'Use of eval() detected',
                    'suggestion': 'Avoid eval() - it can be a security risk'
                })
            
            if 'exec(' in code_str:
                issues.append({
                    'type': 'security',
                    'severity': 'critical',
                    'line': 0,
                    'message': 'Use of exec() detected',
                    'suggestion': 'Avoid exec() - it can be a security risk'
                })
            
        except SyntaxError as e:
            issues.append({
                'type': 'syntax',
                'severity': 'critical',
                'line': e.lineno or 0,
                'message': f'Syntax error: {str(e)}',
                'suggestion': 'Fix syntax errors before reviewing'
            })
        
        return {
            'success': True,
            'issues': issues,
            'suggestions': suggestions,
            'summary': {
                'total_issues': len(issues),
                'total_suggestions': len(suggestions),
                'critical': len([i for i in issues if i['severity'] == 'critical']),
                'high': len([i for i in issues if i['severity'] == 'high']),
                'medium': len([i for i in issues if i['severity'] == 'medium']),
                'low': len([i for i in issues if i['severity'] == 'low'])
            }
        }
    
    def _review_javascript(self, code: str, language: str) -> Dict[str, Any]:
        """Review JavaScript/TypeScript code"""
        issues = []
        suggestions = []
        lines = code.split('\n')
        
        # Check for var usage
        for i, line in enumerate(lines, 1):
            if re.search(r'\bvar\s+', line):
                suggestions.append({
                    'type': 'best_practice',
                    'severity': 'medium',
                    'line': i,
                    'message': 'Use of var detected',
                    'suggestion': 'Use let or const instead of var for better scoping'
                })
            
            # Check for == instead of ===
            if '==' in line and '===' not in line and '!=' not in line:
                suggestions.append({
                    'type': 'best_practice',
                    'severity': 'low',
                    'line': i,
                    'message': 'Use of == instead of ===',
                    'suggestion': 'Use === for strict equality comparison'
                })
            
            # Check for missing semicolons
            stripped = line.strip()
            if (stripped and 
                not stripped.endswith(('{', '}', ';', ',', '(', ')', '[', ']')) and
                not any(keyword in stripped for keyword in ['if', 'for', 'while', 'function', 'else', 'try', 'catch'])):
                suggestions.append({
                    'type': 'style',
                    'severity': 'low',
                    'line': i,
                    'message': 'Missing semicolon',
                    'suggestion': 'Add semicolon at end of statement'
                })
        
        # Check for eval usage
        if 'eval(' in code:
            issues.append({
                'type': 'security',
                'severity': 'critical',
                'line': 0,
                'message': 'Use of eval() detected',
                'suggestion': 'Avoid eval() - it can be a security risk'
            })
        
        return {
            'success': True,
            'issues': issues,
            'suggestions': suggestions,
            'summary': {
                'total_issues': len(issues),
                'total_suggestions': len(suggestions),
                'critical': len([i for i in issues if i['severity'] == 'critical']),
                'high': len([i for i in issues if i['severity'] == 'high']),
                'medium': len([i for i in issues if i['severity'] == 'medium']),
                'low': len([i for i in issues if i['severity'] == 'low'])
            }
        }
    
    def _review_java(self, code: str, language: str) -> Dict[str, Any]:
        """Review Java code"""
        issues = []
        suggestions = []
        lines = code.split('\n')
        
        # Check for missing JavaDoc
        for i, line in enumerate(lines, 1):
            if re.search(r'(public|private|protected)\s+\w+\s+\w+\s*\(', line):
                # Check if previous lines have JavaDoc
                if i > 1 and not lines[i-2].strip().startswith('/**'):
                    suggestions.append({
                        'type': 'documentation',
                        'severity': 'medium',
                        'line': i,
                        'message': 'Method missing JavaDoc comment',
                        'suggestion': 'Add JavaDoc comment above method'
                    })
        
        return {
            'success': True,
            'issues': issues,
            'suggestions': suggestions,
            'summary': {
                'total_issues': len(issues),
                'total_suggestions': len(suggestions),
                'critical': 0,
                'high': 0,
                'medium': len(suggestions),
                'low': 0
            }
        }
    
    def _review_cpp(self, code: str, language: str) -> Dict[str, Any]:
        """Review C/C++ code"""
        issues = []
        suggestions = []
        
        # Check for memory leaks (basic)
        if 'malloc(' in code and 'free(' not in code:
            suggestions.append({
                'type': 'memory',
                'severity': 'high',
                'line': 0,
                'message': 'Potential memory leak',
                'suggestion': 'Ensure all malloc() calls have corresponding free() calls'
            })
        
        return {
            'success': True,
            'issues': issues,
            'suggestions': suggestions,
            'summary': {
                'total_issues': len(issues),
                'total_suggestions': len(suggestions),
                'critical': 0,
                'high': len(suggestions),
                'medium': 0,
                'low': 0
            }
        }
    
    def _review_generic(self, code: str, language: str) -> Dict[str, Any]:
        """Generic code review"""
        return {
            'success': True,
            'issues': [],
            'suggestions': [{
                'type': 'info',
                'severity': 'low',
                'line': 0,
                'message': f'Generic review for {language}',
                'suggestion': 'Consider using language-specific review tools'
            }],
            'summary': {
                'total_issues': 0,
                'total_suggestions': 1,
                'critical': 0,
                'high': 0,
                'medium': 0,
                'low': 1
            }
        }
