"""
Comprehensive AbuLang Runner
Combines all features: basic commands, enhanced features, GUI, calculus, file ops, and multi-format support
"""

import re
import builtins
import math
import statistics
import sys

try:
    from .abu_core import AbuLang
    from .gui_aliases import GUIAliasManager
except ImportError:
    from abu_core import AbuLang
    from gui_aliases import GUIAliasManager


class ComprehensiveAbuRunner:
    """Complete AbuLang interpreter with all features"""

    def __init__(self):
        self.lang = AbuLang()
        self.gui_aliases = GUIAliasManager()
        self.context = {
            "math": math,
            "statistics": statistics,
            "stat": statistics,
            "def_box": self.gui_aliases.def_box,
            "def_circle": self.gui_aliases.def_circle,
            "get_coords": self.gui_aliases.get_coords,
        }
        self.constants = set()

    def execute_line(self, line):
        """Execute a single line of AbuLang code"""
        line = line.strip()
        if not line or line.startswith('#') or line.startswith('//'):
            return

        # Translate syntax enhancements
        line = self.gui_aliases.translate_syntax_enhancements(line)

        # === HELP ===
        if line.startswith("help"):
            self._handle_help(line)
            return

        # === LIBRA (Import) ===
        if line.startswith("libra"):
            self._handle_libra(line)
            return

        # === SHOW (Print) ===
        if line.startswith("show"):
            expr = line[4:].strip()
            if expr.startswith("(") and expr.endswith(")"):
                expr = expr[1:-1].strip()
            value = self.eval_expr(expr)
            print(value)
            return

        # === ASK (Input) ===
        if line.startswith("ask") or line.startswith("sysask"):
            if line.startswith("ask"):
                rest = line[3:].strip()
            else:
                rest = line[6:].strip()
            
            # Check for assignment: var = ask "prompt"
            if "=" in rest:
                var, prompt = map(str.strip, rest.split("=", 1))
                prompt = prompt.strip('"\'')
                self.context[var] = input(prompt)
                return
            else:
                prompt = rest.strip('"\'')
                result = input(prompt)
                print(result)
                return

        # === INVERSE WALRUS OPERATOR =: ===
        # Pattern: x =: 2*y (assigns x and compares to y)
        if "=:" in line:
            parts = line.split("=:")
            if len(parts) == 2:
                var = parts[0].strip()
                expr = parts[1].strip()
                
                # Extract the comparison variable from the expression
                # Look for variable names in the expression
                import re
                var_names = re.findall(r'\b[a-zA-Z_]\w*\b', expr)
                compare_var = var_names[0] if var_names else None
                
                # Evaluate and assign
                value = self.eval_expr(expr)
                self.context[var] = value
                
                # Compare and print
                if compare_var and compare_var in self.context:
                    compare_value = self.context[compare_var]
                    if value > compare_value:
                        print(f"{var}>{compare_var} {value}")
                    elif value < compare_value:
                        print(f"{var}<{compare_var} {value}")
                    else:
                        print(f"{var}=={compare_var} {value}")
                return

        # === VARIABLE ASSIGNMENT ===
        if "=" in line and not line.startswith("if"):
            # Handle "is" operator
            if " is " in line:
                var, expr = map(str.strip, line.split(" is ", 1))
            else:
                var, expr = map(str.strip, line.split("=", 1))
            
            if var in self.constants:
                print(f"[AbuLang Error] Cannot reassign constant '{var}'")
                return
            
            value = self.eval_expr(expr)
            self.context[var] = value
            return

        # === MATH OPERATIONS ===
        # plus, minus, multi, divid, etc.
        math_ops = {
            "plus": lambda a, b: a + b,
            "minus": lambda a, b: a - b,
            "multi": lambda a, b: a * b,
            "divid": lambda a, b: a / b,
            "expon": lambda a, b: a ** b,
            "modul": lambda a, b: a % b,
        }
        
        for op_name, op_func in math_ops.items():
            if line.startswith(op_name):
                parts = line[len(op_name):].strip().split()
                if len(parts) >= 2:
                    a = self.eval_expr(parts[0])
                    b = self.eval_expr(parts[1])
                    result = op_func(a, b)
                    print(result)
                    return

        # === STRING OPERATIONS ===
        string_ops = {
            "strip": lambda s: s.strip(),
            "lower": lambda s: s.lower(),
            "upper": lambda s: s.upper(),
            "lengt": lambda s: len(s),
        }
        
        for op_name, op_func in string_ops.items():
            if line.startswith(op_name):
                expr = line[len(op_name):].strip()
                value = self.eval_expr(expr)
                result = op_func(value)
                print(result)
                return

        # === FALLBACK: Execute as Python ===
        try:
            exec(line, self.context, self.context)
        except Exception as e:
            print(f"[AbuLang Error] {e}")

    def _handle_help(self, line):
        """Handle help command"""
        parts = line.split()
        if len(parts) == 1:
            print("\n📘 AbuLang Help System")
            print("Available commands:")
            print("  show - Display output")
            print("  ask - Get user input")
            print("  libra - Import library")
            print("  plus, minus, multi, divid - Math operations")
            print("  strip, lower, upper - String operations")
            print("\nType 'help all' for full list")
            return

        if parts[1].lower() == "all":
            print("\n📘 AbuLang Full Command List\n")
            for cmd, info in self.lang.commands.items():
                print(f"{cmd:8} | {info.get('section','misc'):10} | {info['desc']}")

    def _handle_libra(self, line):
        """Handle library import"""
        parts = line.split()
        if len(parts) < 2:
            print("[AbuLang Error] No module specified")
            return

        module_name = parts[1].strip()
        
        # Module aliases
        module_aliases = {
            "stat": "statistics",
            "maths": "math",
            "osys": "os",
            "req": "requests",
            "jsons": "json",
            "web": "requests",
            "DISPLAY": "pygame",
            "UI": "tkinter",
            "arrow": "turtle",
        }

        real_module = module_aliases.get(module_name, module_name)

        try:
            import importlib
            imported = importlib.import_module(real_module)
            self.context[real_module] = imported
            
            if module_name != real_module:
                self.context[module_name] = imported
            
            print(f"[libra] imported {real_module}")

            # Special handling for common modules
            if real_module == "statistics":
                self.context["stat"] = imported
            elif real_module == "tkinter":
                self.context["ui"] = imported
                self.context["UI"] = imported
            elif real_module == "pygame":
                self.context["ds"] = imported
                self.context["DISPLAY"] = imported

        except ImportError:
            print(f"[AbuLang Error] could not import {real_module}")

    def eval_expr(self, expr):
        """Evaluate an expression"""
        expr = expr.strip()

        # Handle type casting: str"...", int"...", float"..."
        if expr.startswith('str"') and expr.endswith('"'):
            return expr[4:-1]
        
        if expr.startswith('int"') and expr.endswith('"'):
            content = expr[4:-1]
            try:
                return int(eval(content, self.context, self.context))
            except:
                return int(content)
        
        if expr.startswith('float"') and expr.endswith('"'):
            content = expr[6:-1]
            try:
                return float(eval(content, self.context, self.context))
            except:
                return float(content)

        # Handle string literals
        if re.match(r"^['\"].*['\"]$", expr):
            string_content = expr.strip("\"'")
            # Try to evaluate as number if it looks like one
            try:
                if '.' in string_content:
                    return float(string_content)
                else:
                    return int(string_content)
            except:
                return string_content

        # Handle variable lookup
        if expr in self.context:
            return self.context[expr]

        # Handle math shortcuts
        expr = expr.replace("^", "**")
        expr = re.sub(r"(\d+)%", r"(\1/100)", expr)

        try:
            result = eval(expr, self.context, self.context)
            return result
        except Exception:
            return expr

    def run(self, code: str):
        """Run AbuLang code"""
        lines = code.splitlines()
        i = 0
        
        while i < len(lines):
            line = lines[i]
            
            # Handle comments
            if "#" in line:
                line = line.split("#", 1)[0]
            if "//" in line:
                line = line.split("//", 1)[0]

            line = line.strip()
            
            # Skip empty lines
            if not line:
                i += 1
                continue

            # Check for multi-line blocks (lines ending with :)
            if line.endswith(":"):
                # Collect the block
                block_lines = [line]
                i += 1
                base_indent = None
                
                while i < len(lines):
                    next_line = lines[i]
                    
                    # Skip comments
                    if "#" in next_line:
                        next_line = next_line.split("#", 1)[0]
                    
                    # Check indentation
                    if next_line.strip():
                        indent = len(next_line) - len(next_line.lstrip())
                        
                        if base_indent is None:
                            base_indent = indent
                        
                        # If dedented, block is done
                        if indent < base_indent:
                            break
                        
                        block_lines.append(next_line)
                    else:
                        block_lines.append(next_line)
                    
                    i += 1
                
                # Execute the block
                block_code = '\n'.join(block_lines)
                try:
                    exec(block_code, self.context, self.context)
                except Exception as e:
                    print(f"[AbuLang Error] {e}")
            else:
                # Single line
                self.execute_line(line)
                i += 1


# Alias for compatibility
AbuRunner = ComprehensiveAbuRunner
