#!/usr/bin/env python3
"""
Direct Zexus file executor - no dependencies, just runs .zx files directly
"""
import sys
import os
import argparse

# Add src to path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))

from zexus.lexer import Lexer
from zexus.parser.parser import UltimateParser
from zexus.evaluator.core import Evaluator
from zexus.object import Environment
from zexus import config

def run_zexus_file(filename, debug_level='none', use_vm=False):
    """Execute a Zexus file directly"""
    
    # Set debug level
    config.config.debug_level = debug_level
    config.config.enable_debug_logs = (debug_level != 'none')
    
    if not os.path.exists(filename):
        print(f"❌ Error: File not found: {filename}", file=sys.stderr)
        sys.exit(1)
    
    with open(filename, 'r') as f:
        code = f.read()
    
    try:
        # Tokenize
        lexer = Lexer(code)
        
        # Parse with advanced parsing enabled
        parser = UltimateParser(lexer, enable_advanced_strategies=True)
        ast = parser.parse_program()
        
        if parser.errors:
            print(f"⚠️ Parse errors: {len(parser.errors)}", file=sys.stderr)
            for error in parser.errors[:10]:  # Show first 10 errors
                print(f"  - {error}", file=sys.stderr)
        
        if use_vm:
            # VM Execution Path (High Performance - Real Implementation)
            print("🚀 Using VM execution mode with bytecode compilation", file=sys.stderr)
            
            try:
                from zexus.vm.vm import VM, VMMode
                from zexus.vm.compiler import compile_ast_to_bytecode, UnsupportedNodeError
                
                # Compile AST to bytecode
                if debug_level != 'none':
                    print("   📦 Compiling AST to bytecode...", file=sys.stderr)
                
                try:
                    bytecode = compile_ast_to_bytecode(ast, optimize=True)
                except UnsupportedNodeError as e:
                    print(f"⚠️  VM fallback: {e}", file=sys.stderr)
                    use_vm = False
                except Exception as e:
                    print(f"⚠️  Bytecode compilation failed: {e}", file=sys.stderr)
                    if debug_level == 'full':
                        import traceback
                        traceback.print_exc(file=sys.stderr)
                    use_vm = False

                if use_vm:
                    if debug_level == 'full' and bytecode is not None:
                        print("\n" + bytecode.disassemble(), file=sys.stderr)
                    
                    if debug_level != 'none':
                        print(f"   ⚡ Executing {len(bytecode.instructions)} instructions...", file=sys.stderr)
                    
                    vm = VM(mode=VMMode.AUTO, use_jit=True, max_heap_mb=512, debug=(debug_level == 'full'))
                    result = vm.execute(bytecode, debug=(debug_level == 'full'))
                    
                    if debug_level != 'none':
                        print(f"   ✅ VM execution complete", file=sys.stderr)
                
            except ImportError as e:
                print(f"⚠️  VM not available: {e}", file=sys.stderr)
                print("   Falling back to evaluator...", file=sys.stderr)
                use_vm = False  # Fall through to evaluator
            except Exception as e:
                print(f"⚠️  VM execution failed: {e}", file=sys.stderr)
                if debug_level == 'full':
                    import traceback
                    traceback.print_exc(file=sys.stderr)
                print("   Falling back to evaluator...", file=sys.stderr)
                use_vm = False  # Fall through to evaluator
        
        if not use_vm:
            # Standard Evaluator Path (Stable - Lower Performance)
            evaluator = Evaluator()
            env = Environment()
            result = evaluator.eval_node(ast, env)
        
        # Check if result is an error
        from zexus.object import Null, EvaluationError
        if isinstance(result, EvaluationError):
            print(f"❌ Runtime Error: {result.message}", file=sys.stderr)
            sys.exit(1)
        
        # Print final result if not NULL
        if result and not isinstance(result, Null):
            print(f"Result: {result}")
        
    except Exception as e:
        print(f"\n❌ Error: {str(e)}", file=sys.stderr)
        import traceback
        print("\nFull traceback:", file=sys.stderr)
        traceback.print_exc(file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Zexus file executor')
    parser.add_argument('file', help='Zexus file to execute (.zx)')
    parser.add_argument('--verbose', '-v', action='store_true', 
                        help='Enable verbose debug output')
    parser.add_argument('--quiet', '-q', action='store_true',
                        help='Suppress parser debug output (default)')
    parser.add_argument('--use-vm', action='store_true',
                        help='Use VM execution mode for better performance (experimental)')
    
    args = parser.parse_args()
    
    # Determine debug level
    if args.verbose:
        debug_level = 'full'
    else:
        debug_level = 'none'
    
    run_zexus_file(args.file, debug_level, use_vm=args.use_vm)
