"""
AbuLang Smart Interpreter - Groundbreaking Syntax Features
- Smart string interpolation (no quotes needed, auto str() conversion)
- Smart number types (7.0 → int, 7.5 → float)
- Built-in ascii() and binary()/bny() functions
- Internal libraries (math, stat) vs external (libra for tensorflow, etc.)
"""

import re
import math
import statistics
import ast


class SmartInterpreter:
    """Enhanced AbuLang interpreter with smart features"""
    
    def __init__(self):
        self.context = {
            # Built-in modules (no libra needed)
            "math": math,
            "stat": statistics,
            "statistics": statistics,
            
            # Built-in functions
            "ascii": self._ascii_func,
            "binary": self._binary_func,
            "bny": self._binary_func,
        }
        self.constants = set()
        
    def _ascii_func(self, text):
        """Get ASCII values of string characters"""
        if isinstance(text, str):
            if len(text) == 1:
                return ord(text)
            return [ord(c) for c in text]
        return ord(str(text)[0])
    
    def _binary_func(self, value):
        """Convert to binary representation"""
        if isinstance(value, str):
            # Convert string to binary via ASCII
            if len(value) == 1:
                return bin(ord(value))
            return [bin(ord(c)) for c in value]
        elif isinstance(value, int):
            return bin(value)
        elif isinstance(value, float):
            return bin(int(value))
        else:
            return bin(ord(str(value)[0]))
    
    def smart_number(self, value):
        """
        Smart number type conversion:
        - 7.0 → 7 (int)
        - 7.5 → 7.5 (float)
        - 5 → 5 (int)
        """
        if isinstance(value, str):
            try:
                if '.' in value:
                    float_val = float(value)
                    # Check if it's a whole number
                    if float_val.is_integer():
                        return int(float_val)
                    return float_val
                else:
                    return int(value)
            except ValueError:
                return value
        elif isinstance(value, float):
            if value.is_integer():
                return int(value)
        return value
    
    def smart_interpolate(self, text):
        """
        Smart string interpolation:
        - Automatically converts variables to strings
        - No need for str() calls
        - Supports {variable} syntax
        
        Examples:
            age = 25
            show "Age: {age}"  # Works without str()
            show "Result: {x + y}"  # Evaluates expressions
        """
        if not isinstance(text, str):
            return str(text)
        
        # Find all {expression} patterns
        pattern = r'\{([^}]+)\}'
        
        def replace_expr(match):
            expr = match.group(1).strip()
            try:
                # Evaluate the expression in current context
                result = self.eval_expr(expr)
                return str(result)
            except Exception:
                return match.group(0)  # Return original if evaluation fails
        
        return re.sub(pattern, replace_expr, text)
    
    def execute_line(self, line):
        """Execute a single line of AbuLang code with smart features"""
        line = line.strip()
        if not line or line.startswith('#') or line.startswith('//'):
            return
        
        # === SHOW command with smart interpolation ===
        if line.startswith('show'):
            expr = line[4:].strip()
            
            # Handle show without quotes (smart interpolation)
            if not (expr.startswith('"') or expr.startswith("'")):
                # Direct variable or expression
                value = self.eval_expr(expr)
                print(value)
                return
            
            # Remove quotes
            if expr.startswith('(') and expr.endswith(')'):
                expr = expr[1:-1].strip()
            
            # Evaluate the expression
            value = self.eval_expr(expr)
            
            # Apply smart interpolation if it's a string
            if isinstance(value, str):
                value = self.smart_interpolate(value)
            
            print(value)
            return
        
        # === ASK command ===
        if line.startswith('ask'):
            expr = line[3:].strip()
            if expr.startswith('(') and expr.endswith(')'):
                expr = expr[1:-1].strip()
            
            # Smart interpolation for prompt
            prompt = self.eval_expr(expr)
            if isinstance(prompt, str):
                prompt = self.smart_interpolate(prompt)
            else:
                prompt = str(prompt)
            
            result = input(prompt)
            return result
        
        # === Variable assignment with "is" ===
        if ' is ' in line and not line.startswith('if') and not line.startswith('when'):
            var, expr = line.split(' is ', 1)
            var = var.strip()
            expr = expr.strip()
            
            if var in self.constants:
                print(f"[AbuLang Error] Cannot reassign constant '{var}'")
                return
            
            value = self.eval_expr(expr)
            value = self.smart_number(value)  # Apply smart number conversion
            self.context[var] = value
            return
        
        # === Variable assignment with "=" ===
        if '=' in line and not any(op in line for op in ['==', '!=', '>=', '<=']) and not line.startswith('if') and not line.startswith('when'):
            var, expr = line.split('=', 1)
            var = var.strip()
            expr = expr.strip()
            
            if var in self.constants:
                print(f"[AbuLang Error] Cannot reassign constant '{var}'")
                return
            
            value = self.eval_expr(expr)
            value = self.smart_number(value)  # Apply smart number conversion
            self.context[var] = value
            return
        
        # === LIBRA (import) - Only for EXTERNAL libraries ===
        if line.startswith('libra'):
            parts = line.split()
            if len(parts) < 2:
                print("[AbuLang Error] No module specified")
                return
            
            module_name = parts[1].strip()
            
            # Check if it's an internal module
            internal_modules = ['math', 'stat', 'statistics', 'random', 're', 'json', 'datetime', 'collections']
            if module_name in internal_modules or module_name in ['maths']:
                print(f"[AbuLang Info] '{module_name}' is built-in, no need for 'libra'")
                print(f"Just use: {module_name}.function()")
                return
            
            # External library import
            try:
                import importlib
                imported = importlib.import_module(module_name)
                self.context[module_name] = imported
                print(f"[libra] imported external library: {module_name}")
            except ImportError:
                print(f"[AbuLang Error] External library '{module_name}' not found")
                print("Install it with: pip install " + module_name)
            return
        
        # === Fallback: execute as Python ===
        try:
            exec(line, self.context, self.context)
        except Exception as e:
            print(f"[AbuLang Error] {e}")
    
    def eval_expr(self, expr):
        """Evaluate an expression with smart features"""
        expr = expr.strip()
        
        # Handle string literals
        if (expr.startswith('"') and expr.endswith('"')) or (expr.startswith("'") and expr.endswith("'")):
            return expr[1:-1]
        
        # 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)
            result = self.smart_number(result)  # Apply smart number conversion
            return result
        except Exception:
            return expr
    
    def run(self, code):
        """Run AbuLang code with smart features"""
        lines = code.splitlines()
        
        for line in lines:
            # Handle comments
            if '#' in line:
                line = line.split('#', 1)[0]
            if '//' in line:
                line = line.split('//', 1)[0]
            
            line = line.strip()
            if not line:
                continue
            
            # Handle variable assignment from ask
            if '=' in line and 'ask' in line:
                var, rest = line.split('=', 1)
                var = var.strip()
                rest = rest.strip()
                
                if rest.startswith('ask'):
                    expr = rest[3:].strip()
                    if expr.startswith('(') and expr.endswith(')'):
                        expr = expr[1:-1].strip()
                    
                    # Smart interpolation for prompt
                    prompt = self.eval_expr(expr)
                    if isinstance(prompt, str):
                        prompt = self.smart_interpolate(prompt)
                    else:
                        prompt = str(prompt)
                    
                    result = input(prompt)
                    result = self.smart_number(result)  # Try to convert to number
                    self.context[var] = result
                    continue
            
            self.execute_line(line)


# Export for use in other modules
if __name__ == "__main__":
    # Test the smart interpreter
    interpreter = SmartInterpreter()
    
    print("=== Testing Smart Features ===\n")
    
    # Test 1: Smart number types
    print("Test 1: Smart Number Types")
    interpreter.run("""
x = 7.0
y = 7.5
z = 5
show x
show y
show z
""")
    
    print("\nTest 2: Smart String Interpolation")
    interpreter.run("""
name = "Abu"
age = 25
show "Name: {name}, Age: {age}"
show "Next year: {age + 1}"
""")
    
    print("\nTest 3: ASCII and Binary Functions")
    interpreter.run("""
show ascii("A")
show ascii("Hello")
show binary(65)
show bny("A")
""")
    
    print("\nTest 4: Built-in Math (no libra needed)")
    interpreter.run("""
show math.sqrt(16)
show stat.mean([1, 2, 3, 4, 5])
""")
