"""
Code Converter 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 json
from typing import Dict, List, Any, Optional

class CodeConverter:
    """
    Advanced code conversion between programming languages
    """
    
    def __init__(self):
        self.supported_conversions = {
            'python': ['javascript', 'java', 'cpp', 'csharp'],
            'javascript': ['python', 'typescript', 'java'],
            'java': ['python', 'cpp', 'csharp'],
            'cpp': ['python', 'java', 'c'],
            'csharp': ['python', 'java', 'cpp'],
            'typescript': ['javascript', 'python'],
            'php': ['python', 'javascript'],
            'go': ['python', 'cpp'],
            'rust': ['cpp', 'python']
        }
        
        self.language_mappings = {
            'python': {
                'keywords': {
                    'def': 'function',
                    'class': 'class',
                    'if': 'if',
                    'else': 'else',
                    'elif': 'else if',
                    'for': 'for',
                    'while': 'while',
                    'try': 'try',
                    'except': 'catch',
                    'finally': 'finally',
                    'import': 'import',
                    'from': 'import',
                    'return': 'return',
                    'break': 'break',
                    'continue': 'continue',
                    'pass': 'pass',
                    'None': 'null',
                    'True': 'true',
                    'False': 'false',
                    'and': '&&',
                    'or': '||',
                    'not': '!'
                },
                'data_types': {
                    'str': 'string',
                    'int': 'number',
                    'float': 'number',
                    'bool': 'boolean',
                    'list': 'Array',
                    'dict': 'Object',
                    'tuple': 'Array'
                }
            },
            'javascript': {
                'keywords': {
                    'function': 'def',
                    'class': 'class',
                    'if': 'if',
                    'else': 'else',
                    'for': 'for',
                    'while': 'while',
                    'try': 'try',
                    'catch': 'except',
                    'finally': 'finally',
                    'import': 'import',
                    'return': 'return',
                    'break': 'break',
                    'continue': 'continue',
                    'null': 'None',
                    'true': 'True',
                    'false': 'False',
                    '&&': 'and',
                    '||': 'or',
                    '!': 'not'
                },
                'data_types': {
                    'string': 'str',
                    'number': 'int',
                    'boolean': 'bool',
                    'Array': 'list',
                    'Object': 'dict'
                }
            }
        }
    
    def convert_code(self, code: str, from_lang: str, to_lang: str) -> Dict[str, Any]:
        """
        Convert code from one language to another
        """
        try:
            if from_lang not in self.supported_conversions:
                return {
                    'success': False,
                    'error': f'Source language {from_lang} not supported',
                    'converted_code': ''
                }
            
            if to_lang not in self.supported_conversions[from_lang]:
                return {
                    'success': False,
                    'error': f'Conversion from {from_lang} to {to_lang} not supported',
                    'converted_code': ''
                }
            
            # Perform conversion based on language pair
            conversion_method = f'_convert_{from_lang}_to_{to_lang}'
            if hasattr(self, conversion_method):
                result = getattr(self, conversion_method)(code)
            else:
                # Use generic conversion
                result = self._generic_convert(code, from_lang, to_lang)
            
            return {
                'success': True,
                'converted_code': result['code'],
                'changes_made': result['changes'],
                'warnings': result.get('warnings', []),
                'from_language': from_lang,
                'to_language': to_lang
            }
            
        except Exception as e:
            return {
                'success': False,
                'error': f'Conversion failed: {str(e)}',
                'converted_code': ''
            }
    
    def _convert_python_to_javascript(self, code: str) -> Dict[str, Any]:
        """Convert Python code to JavaScript"""
        changes = []
        warnings = []
        js_code = code
        
        # Convert function definitions
        js_code = re.sub(r'def\s+(\w+)\s*\(([^)]*)\):', r'function \1(\2) {', js_code)
        changes.append('Function definitions converted')
        
        # Convert class definitions
        js_code = re.sub(r'class\s+(\w+)(?:\([^)]*\))?:', r'class \1 {', js_code)
        changes.append('Class definitions converted')
        
        # Convert if/elif/else
        js_code = re.sub(r'elif\s+', 'else if ', js_code)
        changes.append('elif converted to else if')
        
        # Convert boolean values
        js_code = js_code.replace('True', 'true').replace('False', 'false')
        js_code = js_code.replace('None', 'null')
        changes.append('Boolean and null values converted')
        
        # Convert logical operators
        js_code = js_code.replace(' and ', ' && ').replace(' or ', ' || ')
        js_code = js_code.replace(' not ', ' !')
        changes.append('Logical operators converted')
        
        # Convert print statements
        js_code = re.sub(r'print\s*\(([^)]+)\)', r'console.log(\1)', js_code)
        changes.append('print statements converted to console.log')
        
        # Convert list/dict literals
        js_code = js_code.replace('[', '[').replace(']', ']')  # Keep as is
        js_code = js_code.replace('{', '{').replace('}', '}')    # Keep as is
        
        # Convert indentation to braces (basic)
        lines = js_code.split('\n')
        brace_lines = []
        indent_stack = [0]
        
        for line in lines:
            stripped = line.strip()
            if not stripped:
                brace_lines.append('')
                continue
            
            current_indent = len(line) - len(line.lstrip())
            
            # Close braces for reduced indentation
            while current_indent < indent_stack[-1]:
                brace_lines.append(' ' * indent_stack[-2] + '}')
                indent_stack.pop()
            
            # Add the current line
            if stripped.endswith(':'):
                brace_lines.append(line.rstrip(':') + ' {')
                indent_stack.append(current_indent + 4)
            else:
                brace_lines.append(line + ';')
        
        # Close remaining braces
        while len(indent_stack) > 1:
            brace_lines.append(' ' * indent_stack[-2] + '}')
            indent_stack.pop()
        
        js_code = '\n'.join(brace_lines)
        changes.append('Python indentation converted to JavaScript braces')
        
        # Add warnings for unsupported features
        if 'import ' in js_code:
            warnings.append('Python imports may need manual conversion to ES6 imports')
        
        if '__' in js_code:
            warnings.append('Python dunder methods may need manual conversion')
        
        return {
            'code': js_code,
            'changes': changes,
            'warnings': warnings
        }
    
    def _convert_javascript_to_python(self, code: str) -> Dict[str, Any]:
        """Convert JavaScript code to Python"""
        changes = []
        warnings = []
        py_code = code
        
        # Convert function definitions
        py_code = re.sub(r'function\s+(\w+)\s*\(([^)]*)\)\s*{', r'def \1(\2):', py_code)
        py_code = re.sub(r'const\s+(\w+)\s*=\s*\(([^)]*)\)\s*=>', r'def \1(\2):', py_code)
        changes.append('Function definitions converted')
        
        # Convert class definitions
        py_code = re.sub(r'class\s+(\w+)\s*{', r'class \1:', py_code)
        changes.append('Class definitions converted')
        
        # Convert else if to elif
        py_code = py_code.replace('else if', 'elif')
        changes.append('else if converted to elif')
        
        # Convert boolean values
        py_code = py_code.replace('true', 'True').replace('false', 'False')
        py_code = py_code.replace('null', 'None')
        changes.append('Boolean and None values converted')
        
        # Convert logical operators
        py_code = py_code.replace(' && ', ' and ').replace(' || ', ' or ')
        py_code = re.sub(r'\s*!\s*', ' not ', py_code)
        changes.append('Logical operators converted')
        
        # Convert console.log to print
        py_code = re.sub(r'console\.log\s*\(([^)]+)\)', r'print(\1)', py_code)
        changes.append('console.log converted to print')
        
        # Convert braces to indentation (basic)
        lines = py_code.split('\n')
        indent_lines = []
        indent_level = 0
        
        for line in lines:
            stripped = line.strip()
            if not stripped:
                indent_lines.append('')
                continue
            
            # Handle closing braces
            if stripped == '}':
                indent_level = max(0, indent_level - 1)
                continue
            
            # Handle opening braces
            if stripped.endswith('{'):
                indent_lines.append('    ' * indent_level + stripped[:-1].strip() + ':')
                indent_level += 1
            else:
                # Remove semicolons and add proper indentation
                clean_line = stripped.rstrip(';')
                indent_lines.append('    ' * indent_level + clean_line)
        
        py_code = '\n'.join(indent_lines)
        changes.append('JavaScript braces converted to Python indentation')
        
        # Add warnings for unsupported features
        if 'var ' in py_code:
            warnings.append('var declarations converted to let - consider scope')
        
        if '=>' in py_code:
            warnings.append('Arrow functions may need manual review')
        
        return {
            'code': py_code,
            'changes': changes,
            'warnings': warnings
        }
    
    def _convert_python_to_java(self, code: str) -> Dict[str, Any]:
        """Convert Python code to Java"""
        changes = []
        warnings = []
        java_code = code
        
        # Convert function definitions
        java_code = re.sub(r'def\s+(\w+)\s*\(([^)]*)\):', r'public static \1(\2) {', java_code)
        changes.append('Function definitions converted to static methods')
        
        # Convert class definitions
        java_code = re.sub(r'class\s+(\w+)(?:\([^)]*\))?:', r'public class \1 {', java_code)
        changes.append('Class definitions converted')
        
        # Convert data types
        java_code = java_code.replace('True', 'true').replace('False', 'false')
        java_code = java_code.replace('None', 'null')
        changes.append('Boolean and null values converted')
        
        # Convert print statements
        java_code = re.sub(r'print\s*\(([^)]+)\)', r'System.out.println(\1)', java_code)
        changes.append('print statements converted to System.out.println')
        
        # Add type declarations (basic)
        java_code = re.sub(r'(\w+)\s*=', 'Object ', java_code)
        changes.append('Variable declarations added (Object type)')
        
        # Add warnings
        warnings.append('Java conversion requires manual type declarations')
        warnings.append('Python dynamic typing may need explicit Java types')
        warnings.append('Consider adding proper package and import statements')
        
        return {
            'code': java_code,
            'changes': changes,
            'warnings': warnings
        }
    
    def _generic_convert(self, code: str, from_lang: str, to_lang: str) -> Dict[str, Any]:
        """Generic conversion using keyword mappings"""
        changes = []
        warnings = []
        converted_code = code
        
        # Get keyword mappings
        from_mapping = self.language_mappings.get(from_lang, {}).get('keywords', {})
        to_mapping = self.language_mappings.get(to_lang, {}).get('keywords', {})
        
        # Apply keyword conversions
        for from_keyword, to_keyword in from_mapping.items():
            if from_keyword in converted_code:
                # Use word boundaries to avoid partial matches
                pattern = r'\b' + re.escape(from_keyword) + r'\b'
                converted_code = re.sub(pattern, to_keyword, converted_code)
                changes.append(f'Converted {from_keyword} to {to_keyword}')
        
        # Add generic warnings
        warnings.append(f'Generic conversion from {from_lang} to {to_lang} - manual review recommended')
        warnings.append('Language-specific features may need manual adjustment')
        
        return {
            'code': converted_code,
            'changes': changes,
            'warnings': warnings
        }
    
    def get_supported_conversions(self) -> Dict[str, List[str]]:
        """Get all supported language conversions"""
        return self.supported_conversions
    
    def detect_language(self, code: str) -> Optional[str]:
        """Detect the programming language of the code"""
        language_patterns = {
            'python': [r'def\s+\w+\s*\(', r'import\s+\w+', r'from\s+\w+\s+import', r'print\s*\('],
            'javascript': [r'function\s+\w+\s*\(', r'const\s+\w+\s*=', r'let\s+\w+\s*=', r'console\.log'],
            'java': [r'public\s+class\s+\w+', r'public\s+static\s+void\s+main', r'System\.out\.println'],
            'cpp': [r'#include\s*<[^>]+>', r'int\s+main\s*\(', r'cout\s*<<', r'cin\s*>>'],
            'csharp': [r'using\s+\w+', r'public\s+class\s+\w+', r'Console\.WriteLine'],
            'php': [r'<\?php', r'\$\w+\s*=', r'echo\s+', r'function\s+\w+\s*\('],
            'ruby': [r'def\s+\w+', r'puts\s+', r'end\s*$', r'@\w+'],
            'go': [r'package\s+\w+', r'func\s+\w+\s*\(', r'fmt\.Print'],
            'rust': [r'fn\s+\w+\s*\(', r'let\s+mut\s+\w+', r'println!'],
            'typescript': [r'interface\s+\w+', r'type\s+\w+', r':\s*\w+\[\]']
        }
        
        scores = {}
        for lang, patterns in language_patterns.items():
            score = 0
            for pattern in patterns:
                if re.search(pattern, code, re.IGNORECASE):
                    score += 1
            scores[lang] = score
        
        # Return language with highest score
        if scores:
            best_lang = max(scores, key=scores.get)
            if scores[best_lang] > 0:
                return best_lang
        
        return None
