"""
AbuLang Error Handler - Enhanced error reporting with line numbers and context
"""

import traceback
import sys
from typing import Optional, List, Tuple


class AbuLangError(Exception):
    """Base exception for AbuLang errors"""
    def __init__(self, message: str, line_number: Optional[int] = None, 
                 line_content: Optional[str] = None, context: Optional[str] = None):
        self.message = message
        self.line_number = line_number
        self.line_content = line_content
        self.context = context
        super().__init__(self.format_error())
    
    def format_error(self) -> str:
        """Format error with line number and context"""
        error_str = f"AbuLang Error: {self.message}"
        
        if self.line_number:
            error_str += f"\n  Line {self.line_number}"
        
        if self.line_content:
            error_str += f": {self.line_content.strip()}"
        
        if self.context:
            error_str += f"\n  Context: {self.context}"
        
        return error_str


class SyntaxError(AbuLangError):
    """Syntax error in AbuLang code"""
    pass


class RuntimeError(AbuLangError):
    """Runtime error during execution"""
    pass


class TypeError(AbuLangError):
    """Type mismatch error"""
    pass


class NameError(AbuLangError):
    """Undefined variable or function"""
    pass


class ErrorHandler:
    """Handles error reporting with enhanced stack traces"""
    
    def __init__(self):
        self.errors: List[AbuLangError] = []
        self.warnings: List[str] = []
        self.debug_mode = False
    
    def enable_debug(self):
        """Enable debug mode for verbose error output"""
        self.debug_mode = True
    
    def disable_debug(self):
        """Disable debug mode"""
        self.debug_mode = False
    
    def report_error(self, error: AbuLangError, show_traceback: bool = True):
        """Report an error with optional traceback"""
        self.errors.append(error)
        
        print(f"\n{'='*60}")
        print(str(error))
        print(f"{'='*60}\n")
        
        if show_traceback and self.debug_mode:
            print("Traceback:")
            traceback.print_exc()
    
    def report_warning(self, message: str, line_number: Optional[int] = None):
        """Report a warning"""
        warning = f"Warning"
        if line_number:
            warning += f" (Line {line_number})"
        warning += f": {message}"
        
        self.warnings.append(warning)
        print(f"⚠️  {warning}")
    
    def get_error_summary(self) -> str:
        """Get summary of all errors"""
        if not self.errors:
            return "No errors"
        
        summary = f"Total errors: {len(self.errors)}\n"
        for i, error in enumerate(self.errors, 1):
            summary += f"{i}. {error.message}"
            if error.line_number:
                summary += f" (Line {error.line_number})"
            summary += "\n"
        
        return summary
    
    def clear(self):
        """Clear error and warning lists"""
        self.errors.clear()
        self.warnings.clear()


class StackTracer:
    """Tracks execution stack for better error reporting"""
    
    def __init__(self):
        self.stack: List[Tuple[str, int]] = []  # (function_name, line_number)
    
    def push(self, function_name: str, line_number: int):
        """Push function call onto stack"""
        self.stack.append((function_name, line_number))
    
    def pop(self):
        """Pop function call from stack"""
        if self.stack:
            self.stack.pop()
    
    def get_stack_trace(self) -> str:
        """Get formatted stack trace"""
        if not self.stack:
            return "Stack trace: (empty)"
        
        trace = "Stack trace:\n"
        for i, (func_name, line_num) in enumerate(self.stack):
            indent = "  " * i
            trace += f"{indent}→ {func_name} (Line {line_num})\n"
        
        return trace
    
    def clear(self):
        """Clear stack"""
        self.stack.clear()


class LineTracker:
    """Tracks current line being executed"""
    
    def __init__(self):
        self.current_line = 0
        self.current_content = ""
        self.lines: List[str] = []
    
    def load_code(self, code: str):
        """Load code and split into lines"""
        self.lines = code.split('\n')
    
    def set_line(self, line_number: int):
        """Set current line being executed"""
        self.current_line = line_number
        if 0 <= line_number < len(self.lines):
            self.current_content = self.lines[line_number]
    
    def get_context(self, context_lines: int = 2) -> str:
        """Get code context around current line"""
        start = max(0, self.current_line - context_lines)
        end = min(len(self.lines), self.current_line + context_lines + 1)
        
        context = ""
        for i in range(start, end):
            marker = ">>> " if i == self.current_line else "    "
            line_num = i + 1
            context += f"{marker}{line_num:4d} | {self.lines[i]}\n"
        
        return context
    
    def get_current_line(self) -> Tuple[int, str]:
        """Get current line number and content"""
        return self.current_line, self.current_content


# Global error handler instance
_error_handler = ErrorHandler()
_stack_tracer = StackTracer()
_line_tracker = LineTracker()


def get_error_handler() -> ErrorHandler:
    """Get global error handler"""
    return _error_handler


def get_stack_tracer() -> StackTracer:
    """Get global stack tracer"""
    return _stack_tracer


def get_line_tracker() -> LineTracker:
    """Get global line tracker"""
    return _line_tracker
