"""
Code Formatter 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, Any, Optional

class CodeFormatter:
    """
    Utility class for formatting and beautifying code
    """
    
    def __init__(self):
        self.supported_languages = [
            'python', 'javascript', 'typescript', 'java', 'cpp', 'c',
            'csharp', 'php', 'ruby', 'go', 'rust', 'html', 'css', 'json'
        ]
    
    def format_code(self, code: str, language: str, style: str = 'standard') -> Dict[str, Any]:
        """
        Format code based on language and style preferences
        """
        try:
            if language not in self.supported_languages:
                return {
                    'success': False,
                    'error': f'Language {language} not supported for formatting',
                    'formatted_code': code
                }
            
            if language == 'python':
                return self._format_python(code, style)
            elif language in ['javascript', 'typescript']:
                return self._format_javascript(code, style)
            elif language == 'json':
                return self._format_json(code)
            elif language == 'html':
                return self._format_html(code, style)
            elif language == 'css':
                return self._format_css(code, style)
            else:
                return self._format_generic(code, language, style)
                
        except Exception as e:
            return {
                'success': False,
                'error': f'Formatting failed: {str(e)}',
                'formatted_code': code
            }
    
    def _format_python(self, code: str, style: str) -> Dict[str, Any]:
        """Format Python code"""
        try:
            # Basic Python formatting
            formatted = code
            
            # Remove trailing whitespace
            lines = formatted.split('\n')
            formatted_lines = [line.rstrip() for line in lines]
            formatted = '\n'.join(formatted_lines)
            
            # Ensure proper spacing around operators
            formatted = re.sub(r'([=+\-*/%<>!&|^])(?=\S)', r'\1 ', formatted)
            formatted = re.sub(r'(?<=\S)([=+\-*/%<>!&|^])', r' \1', formatted)
            
            # Fix spacing around commas
            formatted = re.sub(r',(?!\s)', r', ', formatted)
            
            # Ensure proper spacing after colons
            formatted = re.sub(r':(?!\s)', r': ', formatted)
            
            # Add blank lines between functions/classes
            formatted = re.sub(r'\n(def |class )', r'\n\n\1', formatted)
            formatted = re.sub(r'\n\n\n+', r'\n\n', formatted)
            
            # Try to parse and reformat with proper indentation
            try:
                tree = ast.parse(formatted)
                # ast.unparse is available in Python 3.9+
                if hasattr(ast, 'unparse'):
                    formatted = ast.unparse(tree)
                # For Python < 3.9, use basic formatting
            except (SyntaxError, ValueError):
                pass  # If parsing fails, return basic formatting
            
            return {
                'success': True,
                'formatted_code': formatted,
                'changes_made': ['Removed trailing whitespace', 'Fixed operator spacing', 'Added proper line breaks']
            }
        except Exception as e:
            return {
                'success': False,
                'error': f'Python formatting failed: {str(e)}',
                'formatted_code': code
            }
    
    def _format_javascript(self, code: str, style: str) -> Dict[str, Any]:
        """Format JavaScript/TypeScript code"""
        try:
            formatted = code
            
            # Remove trailing whitespace
            lines = formatted.split('\n')
            formatted_lines = [line.rstrip() for line in lines]
            formatted = '\n'.join(formatted_lines)
            
            # Ensure semicolons at end of statements
            formatted = re.sub(r'([^;{}\n])\n(?=[a-zA-Z])', r'\1;\n', formatted)
            
            # Fix spacing around operators
            formatted = re.sub(r'([=+\-*/%<>!&|^])(?=\S)', r'\1 ', formatted)
            formatted = re.sub(r'(?<=\S)([=+\-*/%<>!&|^])', r' \1', formatted)
            
            # Fix spacing around braces
            formatted = re.sub(r'\{', r'{ ', formatted)
            formatted = re.sub(r'\}', r' }', formatted)
            
            # Add blank lines between functions
            formatted = re.sub(r'\n(function |const |let |var |class )', r'\n\n\1', formatted)
            formatted = re.sub(r'\n\n\n+', r'\n\n', formatted)
            
            return {
                'success': True,
                'formatted_code': formatted,
                'changes_made': ['Removed trailing whitespace', 'Fixed spacing', 'Added proper line breaks']
            }
        except Exception as e:
            return {
                'success': False,
                'error': f'JavaScript formatting failed: {str(e)}',
                'formatted_code': code
            }
    
    def _format_json(self, code: str) -> Dict[str, Any]:
        """Format JSON code"""
        try:
            import json
            parsed = json.loads(code)
            formatted = json.dumps(parsed, indent=4, sort_keys=False)
            
            return {
                'success': True,
                'formatted_code': formatted,
                'changes_made': ['Applied JSON indentation', 'Sorted keys']
            }
        except Exception as e:
            return {
                'success': False,
                'error': f'JSON formatting failed: {str(e)}',
                'formatted_code': code
            }
    
    def _format_html(self, code: str, style: str) -> Dict[str, Any]:
        """Format HTML code"""
        try:
            formatted = code
            
            # Basic HTML formatting
            # Indent nested tags
            lines = formatted.split('\n')
            indent_level = 0
            formatted_lines = []
            
            for line in lines:
                stripped = line.strip()
                if not stripped:
                    formatted_lines.append('')
                    continue
                
                # Decrease indent for closing tags
                if stripped.startswith('</'):
                    indent_level = max(0, indent_level - 1)
                
                # Add indented line
                formatted_lines.append('  ' * indent_level + stripped)
                
                # Increase indent for opening tags (not self-closing)
                if stripped.startswith('<') and not stripped.startswith('</') and not stripped.endswith('/>'):
                    if not any(tag in stripped for tag in ['<br', '<hr', '<img', '<meta', '<link', '<input']):
                        indent_level += 1
            
            formatted = '\n'.join(formatted_lines)
            
            return {
                'success': True,
                'formatted_code': formatted,
                'changes_made': ['Applied HTML indentation', 'Organized tag structure']
            }
        except Exception as e:
            return {
                'success': False,
                'error': f'HTML formatting failed: {str(e)}',
                'formatted_code': code
            }
    
    def _format_css(self, code: str, style: str) -> Dict[str, Any]:
        """Format CSS code"""
        try:
            formatted = code
            
            # Remove extra whitespace
            formatted = re.sub(r'\s+', ' ', formatted)
            
            # Add line breaks after semicolons
            formatted = re.sub(r';\s*', ';\n', formatted)
            
            # Add line breaks after closing braces
            formatted = re.sub(r'\}\s*', '}\n\n', formatted)
            
            # Indent properties
            lines = formatted.split('\n')
            indent_level = 0
            formatted_lines = []
            
            for line in lines:
                stripped = line.strip()
                if not stripped:
                    continue
                
                if stripped.endswith('{'):
                    formatted_lines.append('  ' * indent_level + stripped)
                    indent_level += 1
                elif stripped.startswith('}'):
                    indent_level = max(0, indent_level - 1)
                    formatted_lines.append('  ' * indent_level + stripped)
                else:
                    formatted_lines.append('  ' * indent_level + stripped)
            
            formatted = '\n'.join(formatted_lines)
            
            return {
                'success': True,
                'formatted_code': formatted,
                'changes_made': ['Applied CSS indentation', 'Organized selectors and properties']
            }
        except Exception as e:
            return {
                'success': False,
                'error': f'CSS formatting failed: {str(e)}',
                'formatted_code': code
            }
    
    def _format_generic(self, code: str, language: str, style: str) -> Dict[str, Any]:
        """Generic formatting for other languages"""
        try:
            formatted = code
            
            # Remove trailing whitespace
            lines = formatted.split('\n')
            formatted_lines = [line.rstrip() for line in lines]
            formatted = '\n'.join(formatted_lines)
            
            # Remove multiple blank lines
            formatted = re.sub(r'\n\n\n+', r'\n\n', formatted)
            
            return {
                'success': True,
                'formatted_code': formatted,
                'changes_made': ['Removed trailing whitespace', 'Cleaned up blank lines']
            }
        except Exception as e:
            return {
                'success': False,
                'error': f'Formatting failed: {str(e)}',
                'formatted_code': code
            }
