"""
Code Optimizer 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, Tuple

class CodeOptimizer:
    """
    Advanced code optimization and refactoring utility
    """
    
    def __init__(self):
        self.optimization_rules = {
            'performance': self._performance_optimizations,
            'memory': self._memory_optimizations,
            'readability': self._readability_improvements,
            'security': self._security_enhancements,
            'best_practices': self._best_practices_improvements
        }
    
    def optimize_code(self, code: str, language: str, optimization_types: List[str] = None) -> Dict[str, Any]:
        """
        Optimize code based on specified optimization types
        """
        if optimization_types is None:
            optimization_types = ['performance', 'readability', 'best_practices']
        
        try:
            optimizations = []
            optimized_code = code
            
            for opt_type in optimization_types:
                if opt_type in self.optimization_rules:
                    result = self.optimization_rules[opt_type](code, language)
                    optimizations.extend(result['suggestions'])
                    if result.get('optimized_code'):
                        optimized_code = result['optimized_code']
            
            return {
                'success': True,
                'optimized_code': optimized_code,
                'optimizations': optimizations,
                'improvement_score': self._calculate_improvement_score(code, optimized_code),
                'language': language
            }
            
        except Exception as e:
            return {
                'success': False,
                'error': f'Optimization failed: {str(e)}',
                'optimized_code': code,
                'optimizations': []
            }
    
    def _performance_optimizations(self, code: str, language: str) -> Dict[str, Any]:
        """Apply performance optimizations"""
        suggestions = []
        optimized_code = code
        
        if language == 'python':
            # List comprehension instead of loops
            optimized_code = re.sub(
                r'(\w+)\s*=\s*\[\]\s*\n\s*for\s+(\w+)\s+in\s+(\w+):\s*\n\s*\1\.append\(([^)]+)\)',
                r'\1 = [\4 for \2 in \3]',
                optimized_code,
                flags=re.MULTILINE
            )
            
            # Use join instead of string concatenation in loops
            if 'for' in optimized_code and '+=' in optimized_code:
                suggestions.append({
                    'type': 'performance',
                    'severity': 'medium',
                    'message': 'Consider using str.join() instead of string concatenation in loops',
                    'line': self._find_line_number(optimized_code, 'for')
                })
            
            # Use set for membership testing
            if 'in' in optimized_code and 'list' in optimized_code:
                suggestions.append({
                    'type': 'performance',
                    'severity': 'low',
                    'message': 'Consider using set() for faster membership testing',
                    'line': 0
                })
        
        elif language == 'javascript':
            # Use const/let instead of var
            if 'var ' in optimized_code:
                optimized_code = re.sub(r'\bvar\s+', 'let ', optimized_code)
                suggestions.append({
                    'type': 'performance',
                    'severity': 'medium',
                    'message': 'Replaced var with let for better scoping',
                    'line': 0
                })
            
            # Use arrow functions where appropriate
            optimized_code = re.sub(
                r'function\(([^)]*)\)\s*\{\s*return\s+([^;]+);\s*\}',
                r'((\1) => \2)',
                optimized_code
            )
        
        return {
            'optimized_code': optimized_code,
            'suggestions': suggestions
        }
    
    def _memory_optimizations(self, code: str, language: str) -> Dict[str, Any]:
        """Apply memory optimizations"""
        suggestions = []
        
        if language == 'python':
            # Generator expressions instead of list comprehensions for large datasets
            if 'for' in code and '[' in code:
                suggestions.append({
                    'type': 'memory',
                    'severity': 'medium',
                    'message': 'Consider using generator expressions for large datasets',
                    'line': 0
                })
            
            # Context managers for file operations
            if 'open(' in code and 'with' not in code:
                suggestions.append({
                    'type': 'memory',
                    'severity': 'high',
                    'message': 'Use context managers (with statement) for file operations',
                    'line': self._find_line_number(code, 'open(')
                })
            
            # Delete large objects when done
            if 'del ' not in code and ('list' in code or 'dict' in code):
                suggestions.append({
                    'type': 'memory',
                    'severity': 'low',
                    'message': 'Consider using del to free memory for large objects',
                    'line': 0
                })
        
        return {
            'optimized_code': code,
            'suggestions': suggestions
        }
    
    def _readability_improvements(self, code: str, language: str) -> Dict[str, Any]:
        """Improve code readability"""
        suggestions = []
        optimized_code = code
        
        # Add proper spacing
        optimized_code = re.sub(r'(\w)([=+\-*/%<>!&|^])(\w)', r'\1 \2 \3', optimized_code)
        
        # Fix indentation (basic)
        lines = optimized_code.split('\n')
        for i, line in enumerate(lines):
            if line.strip() and not line.startswith(' ') and not line.startswith('\t'):
                if any(keyword in line for keyword in ['if ', 'for ', 'while ', 'def ', 'class ']):
                    lines[i] = '    ' + line
        
        optimized_code = '\n'.join(lines)
        
        # Add docstrings for functions (Python)
        if language == 'python':
            functions = re.findall(r'def\s+(\w+)\s*\(', code)
            for func in functions:
                if f'def {func}(' in optimized_code and f'"""' not in optimized_code:
                    suggestions.append({
                        'type': 'readability',
                        'severity': 'medium',
                        'message': f'Function "{func}" should have a docstring',
                        'line': self._find_line_number(optimized_code, f'def {func}(')
                    })
        
        # Check line length
        lines = optimized_code.split('\n')
        for i, line in enumerate(lines):
            if len(line) > 100:
                suggestions.append({
                    'type': 'readability',
                    'severity': 'low',
                    'message': f'Line {i+1} is too long ({len(line)} > 100 characters)',
                    'line': i + 1
                })
        
        return {
            'optimized_code': optimized_code,
            'suggestions': suggestions
        }
    
    def _security_enhancements(self, code: str, language: str) -> Dict[str, Any]:
        """Apply security enhancements"""
        suggestions = []
        
        # Check for SQL injection vulnerabilities
        if 'execute(' in code and '%' in code:
            suggestions.append({
                'type': 'security',
                'severity': 'high',
                'message': 'Potential SQL injection vulnerability. Use parameterized queries.',
                'line': self._find_line_number(code, 'execute(')
            })
        
        # Check for hardcoded secrets
        secret_patterns = [
            r'password\s*=\s*["\'][^"\']+["\']',
            r'api_key\s*=\s*["\'][^"\']+["\']',
            r'secret\s*=\s*["\'][^"\']+["\']'
        ]
        
        for pattern in secret_patterns:
            if re.search(pattern, code, re.IGNORECASE):
                suggestions.append({
                    'type': 'security',
                    'severity': 'critical',
                    'message': 'Hardcoded secret detected. Use environment variables.',
                    'line': 0
                })
        
        # Check for eval usage
        if 'eval(' in code:
            suggestions.append({
                'type': 'security',
                'severity': 'critical',
                'message': 'Avoid using eval() - potential code injection risk',
                'line': self._find_line_number(code, 'eval(')
            })
        
        return {
            'optimized_code': code,
            'suggestions': suggestions
        }
    
    def _best_practices_improvements(self, code: str, language: str) -> Dict[str, Any]:
        """Apply best practices improvements"""
        suggestions = []
        
        if language == 'python':
            # Check for PEP 8 compliance
            if re.search(r'[A-Z][a-zA-Z]*\s*=\s*', code):
                suggestions.append({
                    'type': 'best_practices',
                    'severity': 'low',
                    'message': 'Variable names should be snake_case (PEP 8)',
                    'line': 0
                })
            
            # Check for exception handling
            if 'try:' in code and 'except:' in code:
                bare_except = re.search(r'except:\s*$', code, re.MULTILINE)
                if bare_except:
                    suggestions.append({
                        'type': 'best_practices',
                        'severity': 'medium',
                        'message': 'Avoid bare except clauses. Specify exception types.',
                        'line': self._find_line_number(code, 'except:')
                    })
            
            # Check for main guard
            if 'if __name__' not in code and 'def main(' in code:
                suggestions.append({
                    'type': 'best_practices',
                    'severity': 'medium',
                    'message': 'Add if __name__ == "__main__": guard',
                    'line': len(code.split('\n'))
                })
        
        elif language == 'javascript':
            # Check for strict mode
            if "'use strict'" not in code and '"use strict"' not in code:
                suggestions.append({
                    'type': 'best_practices',
                    'severity': 'low',
                    'message': 'Consider adding "use strict" directive',
                    'line': 1
                })
            
            # Check for semicolon usage consistency
            lines = code.split('\n')
            semicolon_lines = [i for i, line in enumerate(lines) if line.strip().endswith(';')]
            if len(semicolon_lines) > 0 and len(semicolon_lines) < len(lines) * 0.5:
                suggestions.append({
                    'type': 'best_practices',
                    'severity': 'low',
                    'message': 'Be consistent with semicolon usage',
                    'line': 0
                })
        
        return {
            'optimized_code': code,
            'suggestions': suggestions
        }
    
    def _find_line_number(self, code: str, pattern: str) -> int:
        """Find line number of a pattern in code"""
        lines = code.split('\n')
        for i, line in enumerate(lines):
            if pattern in line:
                return i + 1
        return 0
    
    def _calculate_improvement_score(self, original: str, optimized: str) -> Dict[str, Any]:
        """Calculate improvement score between original and optimized code"""
        original_lines = len(original.split('\n'))
        optimized_lines = len(optimized.split('\n'))
        
        complexity_reduction = max(0, (original_lines - optimized_lines) / original_lines * 100) if original_lines > 0 else 0
        
        return {
            'lines_reduced': original_lines - optimized_lines,
            'complexity_reduction': round(complexity_reduction, 2),
            'overall_score': min(100, max(0, 50 + complexity_reduction))
        }
