/*!
 * Execution Runner Module - Nyash File and Mode Execution Coordinator
 * 
 * This module handles all execution logic, backend selection, and mode coordination,
 * separated from CLI parsing and the main entry point.
 */

use nyash_rust::cli::CliConfig;
use nyash_rust::{
    box_trait::{NyashBox, StringBox, IntegerBox, BoolBox, VoidBox, AddBox, BoxCore},
    tokenizer::{NyashTokenizer},
    ast::ASTNode,
    parser::NyashParser,
    interpreter::NyashInterpreter,
    mir::{MirCompiler, MirPrinter, MirInstruction},
    backend::VM,
};
use nyash_rust::runtime::{NyashRuntime, NyashRuntimeBuilder};
use nyash_rust::interpreter::SharedState;
use nyash_rust::box_factory::user_defined::UserDefinedBoxFactory;
use nyash_rust::core::model::BoxDeclaration as CoreBoxDecl;
use std::sync::Arc;

#[cfg(feature = "wasm-backend")]
use nyash_rust::backend::{wasm::WasmBackend, aot::AotBackend};

#[cfg(feature = "llvm")]
use nyash_rust::backend::{llvm_compile_and_execute};
use std::{fs, process};
mod modes;
mod demos;

// v2 plugin system imports
use nyash_rust::runtime;
use nyash_rust::runner_plugin_init;
use std::path::PathBuf;

/// Main execution coordinator
pub struct NyashRunner {
    config: CliConfig,
}

/// Minimal task runner: read nyash.toml [env] and [tasks], run the named task via shell
fn run_named_task(name: &str) -> Result<(), String> {
    let cfg_path = "nyash.toml";
    let text = fs::read_to_string(cfg_path).map_err(|e| format!("read {}: {}", cfg_path, e))?;
    let doc = toml::from_str::<toml::Value>(&text).map_err(|e| format!("parse {}: {}", cfg_path, e))?;
    // Apply [env]
    if let Some(env_tbl) = doc.get("env").and_then(|v| v.as_table()) {
        for (k, v) in env_tbl.iter() {
            if let Some(s) = v.as_str() { std::env::set_var(k, s); }
        }
    }
    // Lookup [tasks]
    let tasks = doc.get("tasks").and_then(|v| v.as_table()).ok_or("[tasks] not found in nyash.toml")?;
    let cmd = tasks.get(name).and_then(|v| v.as_str()).ok_or_else(|| format!("task '{}' not found", name))?;
    // Basic variable substitution
    let root = std::env::current_dir().unwrap_or(PathBuf::from(".")).display().to_string();
    let cmd = cmd.replace("{root}", &root);
    // Run via shell
    #[cfg(windows)]
    let status = std::process::Command::new("cmd").args(["/C", &cmd]).status().map_err(|e| e.to_string())?;
    #[cfg(not(windows))]
    let status = std::process::Command::new("sh").arg("-lc").arg(&cmd).status().map_err(|e| e.to_string())?;
    if !status.success() { return Err(format!("task '{}' failed with status {:?}", name, status.code())); }
    Ok(())
}

impl NyashRunner {
    /// Create a new runner with the given configuration
    pub fn new(config: CliConfig) -> Self {
        Self { config }
    }

    /// Run Nyash based on the configuration
    pub fn run(&self) {
        // Run named task from nyash.toml (MVP)
        if let Some(task) = self.config.run_task.clone() {
            if let Err(e) = run_named_task(&task) {
                eprintln!("❌ Task error: {}", e);
                process::exit(1);
            }
            return;
        }
        // Verbose CLI flag maps to env for downstream helpers/scripts
        if self.config.cli_verbose { std::env::set_var("NYASH_CLI_VERBOSE", "1"); }
        // Script-level env directives (special comments) — parse early
        // Supported:
        //   // @env KEY=VALUE
        //   // @jit-debug           (preset: exec, threshold=1, events+trace)
        //   // @plugin-builtins     (NYASH_USE_PLUGIN_BUILTINS=1)
        if let Some(ref filename) = self.config.file {
            if let Ok(code) = fs::read_to_string(filename) {
                // Scan first 128 lines for directives
                for (i, line) in code.lines().take(128).enumerate() {
                    let l = line.trim();
                    if !(l.starts_with("//") || l.starts_with("#!") || l.is_empty()) {
                        // Stop early at first non-comment line to avoid scanning full file
                        if i > 0 { break; }
                    }
                    // Shebang with envs: handled by shell normally; keep placeholder
                    if let Some(rest) = l.strip_prefix("//") { let rest = rest.trim();
                        if let Some(dir) = rest.strip_prefix("@env ") {
                            if let Some((k,v)) = dir.split_once('=') {
                                let key = k.trim(); let val = v.trim();
                                if !key.is_empty() { std::env::set_var(key, val); }
                            }
                        } else if rest == "@jit-debug" {
                            std::env::set_var("NYASH_JIT_EXEC", "1");
                            std::env::set_var("NYASH_JIT_THRESHOLD", "1");
                            std::env::set_var("NYASH_JIT_EVENTS", "1");
                            std::env::set_var("NYASH_JIT_EVENTS_COMPILE", "1");
                            std::env::set_var("NYASH_JIT_EVENTS_RUNTIME", "1");
                            std::env::set_var("NYASH_JIT_SHIM_TRACE", "1");
                        } else if rest == "@plugin-builtins" {
                            std::env::set_var("NYASH_USE_PLUGIN_BUILTINS", "1");
                        } else if rest == "@jit-strict" {
                            std::env::set_var("NYASH_JIT_STRICT", "1");
                            std::env::set_var("NYASH_JIT_ARGS_HANDLE_ONLY", "1");
                            // In strict mode, default to JIT-only (no VM fallback)
                            if std::env::var("NYASH_JIT_ONLY").ok().is_none() { std::env::set_var("NYASH_JIT_ONLY", "1"); }
                        }
                    }
                }
            }
        }

        // If strict mode requested via env, ensure handle-only shim behavior is enabled
        if std::env::var("NYASH_JIT_STRICT").ok().as_deref() == Some("1") {
            if std::env::var("NYASH_JIT_ARGS_HANDLE_ONLY").ok().is_none() {
                std::env::set_var("NYASH_JIT_ARGS_HANDLE_ONLY", "1");
            }
            // Enforce JIT-only by default in strict mode unless explicitly overridden
            if std::env::var("NYASH_JIT_ONLY").ok().is_none() {
                std::env::set_var("NYASH_JIT_ONLY", "1");
            }
        }

        // 🏭 Phase 9.78b: Initialize unified registry
        runtime::init_global_unified_registry();
        
        // Try to initialize BID plugins from nyash.toml (best-effort)
        // Allow disabling during snapshot/CI via NYASH_DISABLE_PLUGINS=1
        if std::env::var("NYASH_DISABLE_PLUGINS").ok().as_deref() != Some("1") {
            runner_plugin_init::init_bid_plugins();
        }

        // Optional: enable VM stats via CLI flags
        if self.config.vm_stats {
            std::env::set_var("NYASH_VM_STATS", "1");
        }
        if self.config.vm_stats_json {
            // Prefer explicit JSON flag over any default
            std::env::set_var("NYASH_VM_STATS_JSON", "1");
        }
        // Optional: JIT controls via CLI flags (centralized)
        {
            // CLI opt-in for JSONL events
            if self.config.jit_events { std::env::set_var("NYASH_JIT_EVENTS", "1"); }
            if self.config.jit_events_compile { std::env::set_var("NYASH_JIT_EVENTS_COMPILE", "1"); }
            if self.config.jit_events_runtime { std::env::set_var("NYASH_JIT_EVENTS_RUNTIME", "1"); }
            if let Some(ref p) = self.config.jit_events_path { std::env::set_var("NYASH_JIT_EVENTS_PATH", p); }
            let mut jc = nyash_rust::jit::config::JitConfig::from_env();
            jc.exec |= self.config.jit_exec;
            jc.stats |= self.config.jit_stats;
            jc.stats_json |= self.config.jit_stats_json;
            jc.dump |= self.config.jit_dump;
            if self.config.jit_threshold.is_some() { jc.threshold = self.config.jit_threshold; }
            jc.phi_min |= self.config.jit_phi_min;
            jc.hostcall |= self.config.jit_hostcall;
            jc.handle_debug |= self.config.jit_handle_debug;
            jc.native_f64 |= self.config.jit_native_f64;
            jc.native_bool |= self.config.jit_native_bool;
            // If observability is enabled and no threshold is provided, force threshold=1 so lowering runs and emits events
            let events_on = std::env::var("NYASH_JIT_EVENTS").ok().as_deref() == Some("1")
                || std::env::var("NYASH_JIT_EVENTS_COMPILE").ok().as_deref() == Some("1")
                || std::env::var("NYASH_JIT_EVENTS_RUNTIME").ok().as_deref() == Some("1");
            if events_on && jc.threshold.is_none() { jc.threshold = Some(1); }
            if self.config.jit_only { std::env::set_var("NYASH_JIT_ONLY", "1"); }
            // Apply runtime capability probe (e.g., disable b1 ABI if unsupported)
            let caps = nyash_rust::jit::config::probe_capabilities();
            jc = nyash_rust::jit::config::apply_runtime_caps(jc, caps);
            // Optional DOT emit via CLI (ensures dump is on when path specified)
            if let Some(path) = &self.config.emit_cfg {
                std::env::set_var("NYASH_JIT_DOT", path);
                jc.dump = true;
            }
            // Persist to env (CLI parity) and set as current
            jc.apply_env();
            nyash_rust::jit::config::set_current(jc.clone());
        }
        // Architectural pivot: JIT is compiler-only (EXE/AOT). Ensure VM runtime does not dispatch to JIT
        // unless explicitly requested via independent JIT mode, or when emitting AOT objects.
        if !self.config.compile_native && !self.config.jit_direct {
            // When AOT object emission is requested, allow JIT to run for object generation
            let aot_obj = std::env::var("NYASH_AOT_OBJECT_OUT").ok();
            if aot_obj.is_none() || aot_obj.as_deref() == Some("") {
                // Force-disable runtime JIT execution path for VM/Interpreter flows
                std::env::set_var("NYASH_JIT_EXEC", "0");
            }
        }
        // Benchmark mode - can run without a file
        if self.config.benchmark {
            println!("📊 Nyash Performance Benchmark Suite");
            println!("====================================");
            println!("Running {} iterations per test...", self.config.iterations);
            println!();
            
            self.execute_benchmark_mode();
            return;
        }

        if let Some(ref filename) = self.config.file {
            // Independent JIT direct mode (no VM execute path)
            if self.config.jit_direct {
                self.run_file_jit_direct(filename);
                return;
            }
            // Delegate file-mode execution to modes::common dispatcher
            self.run_file(filename);
        } else {
            self.execute_demo_mode();
        }
    }

    // init_bid_plugins moved to runner_plugin_init.rs

    /// Execute file-based mode with backend selection

    /// Execute demo mode with all demonstrations
    fn execute_demo_mode(&self) {
        println!("🦀 Nyash Rust Implementation - Everything is Box! 🦀");
        println!("====================================================");
        demos::demo_basic_boxes();
        demos::demo_box_operations();
        demos::demo_box_collections();
        demos::demo_environment_system();
        demos::demo_tokenizer_system();
        demos::demo_parser_system();
        demos::demo_interpreter_system();
        println!("\n🎉 All Box operations completed successfully!");
        println!("Memory safety guaranteed by Rust's borrow checker! 🛡️");
    }

    /// Execute Nyash file with interpreter (moved to modes/common.rs)
    #[cfg(any())]
    fn execute_nyash_file(&self, filename: &str) {
        // Read the file
        let code = match fs::read_to_string(filename) {
            Ok(content) => content,
            Err(e) => {
                eprintln!("❌ Error reading file {}: {}", filename, e);
                process::exit(1);
            }
        };
        
        println!("📝 File contents:\n{}", code);
        println!("\n🚀 Parsing and executing...\n");
        
        // Test: immediate file creation (use relative path to avoid sandbox issues)
        std::fs::create_dir_all("development/debug_hang_issue").ok();
        std::fs::write("development/debug_hang_issue/test.txt", "START").ok();
        
        // Parse the code with debug fuel limit
        eprintln!("🔍 DEBUG: Starting parse with fuel: {:?}...", self.config.debug_fuel);
        let ast = match NyashParser::parse_from_string_with_fuel(&code, self.config.debug_fuel) {
            Ok(ast) => {
                eprintln!("🔍 DEBUG: Parse completed, AST created");
                ast
            },
            Err(e) => {
                eprintln!("❌ Parse error: {}", e);
                process::exit(1);
            }
        };
        
        eprintln!("🔍 DEBUG: About to print parse success message...");
        println!("✅ Parse successful!");
        eprintln!("🔍 DEBUG: Parse success message printed");
        
        // Debug log file write
        if let Ok(mut file) = std::fs::OpenOptions::new()
            .create(true)
            .append(true)
            .open("development/debug_hang_issue/debug_trace.log") 
        {
            use std::io::Write;
            let _ = writeln!(file, "=== MAIN: Parse successful ===");
            let _ = file.flush();
        }
        
        eprintln!("🔍 DEBUG: Creating interpreter...");
        
        // Execute the AST
        let mut interpreter = NyashInterpreter::new();
        eprintln!("🔍 DEBUG: Starting execution...");
        match interpreter.execute(ast) {
            Ok(result) => {
                println!("✅ Execution completed successfully!");
                println!("Result: {}", result.to_string_box().value);
                // Structured concurrency: best-effort join of spawned tasks at program end
                let join_ms: u64 = std::env::var("NYASH_JOIN_ALL_MS").ok().and_then(|s| s.parse().ok()).unwrap_or(2000);
                nyash_rust::runtime::global_hooks::join_all_registered_futures(join_ms);
            },
            Err(e) => {
                // Use enhanced error reporting with source context
                eprintln!("❌ Runtime error:\n{}", e.detailed_message(Some(&code)));
                process::exit(1);
            }
        }
    }

    /// Execute MIR compilation and processing mode (moved to modes/mir.rs)
    #[cfg(any())]
    fn execute_mir_mode(&self, filename: &str) {
        // Read the file
        let code = match fs::read_to_string(filename) {
            Ok(content) => content,
            Err(e) => {
                eprintln!("❌ Error reading file {}: {}", filename, e);
                process::exit(1);
            }
        };

        // Parse to AST
        let ast = match NyashParser::parse_from_string(&code) {
            Ok(ast) => ast,
            Err(e) => {
                eprintln!("❌ Parse error: {}", e);
                process::exit(1);
            }
        };

        // Compile to MIR (opt passes configurable)
        let mut mir_compiler = MirCompiler::with_options(!self.config.no_optimize);
        let compile_result = match mir_compiler.compile(ast) {
            Ok(result) => result,
            Err(e) => {
                eprintln!("❌ MIR compilation error: {}", e);
                process::exit(1);
            }
        };

        // Verify MIR if requested
        if self.config.verify_mir {
            println!("🔍 Verifying MIR...");
            match &compile_result.verification_result {
                Ok(()) => println!("✅ MIR verification passed!"),
                Err(errors) => {
                    eprintln!("❌ MIR verification failed:");
                    for error in errors {
                        eprintln!("  • {}", error);
                    }
                    process::exit(1);
                }
            }
        }

        // Dump MIR if requested
        if self.config.dump_mir {
            let mut printer = if self.config.mir_verbose { MirPrinter::verbose() } else { MirPrinter::new() };
            if self.config.mir_verbose_effects { printer.set_show_effects_inline(true); }
            
            println!("🚀 MIR Output for {}:", filename);
            println!("{}", printer.print_module(&compile_result.module));
        }
    }

    /// Execute VM mode (moved to modes/vm.rs)
    #[cfg(any())]
    fn execute_vm_mode(&self, filename: &str) {
        // Read the file
        let code = match fs::read_to_string(filename) {
            Ok(content) => content,
            Err(e) => {
                eprintln!("❌ Error reading file {}: {}", filename, e);
                process::exit(1);
            }
        };

        // Parse to AST
        let ast = match NyashParser::parse_from_string(&code) {
            Ok(ast) => ast,
            Err(e) => {
                eprintln!("❌ Parse error: {}", e);
                process::exit(1);
            }
        };

        // Prepare runtime and collect Box declarations for VM user-defined types
        let runtime = {
            let rt = NyashRuntimeBuilder::new()
                .with_builtin_groups(BuiltinGroups::native_full())
                .build();
            self.collect_box_declarations(&ast, &rt);
            // Register UserDefinedBoxFactory backed by the same declarations
            let mut shared = SharedState::new();
            shared.box_declarations = rt.box_declarations.clone();
            let udf = Arc::new(UserDefinedBoxFactory::new(shared));
            if let Ok(mut reg) = rt.box_registry.lock() {
                reg.register(udf);
            }
            rt
        };

        // Compile to MIR (opt passes configurable)
        let mut mir_compiler = MirCompiler::with_options(!self.config.no_optimize);
        let compile_result = match mir_compiler.compile(ast) {
            Ok(result) => result,
            Err(e) => {
                eprintln!("❌ MIR compilation error: {}", e);
                process::exit(1);
            }
        };

        // Execute with VM using prepared runtime
        let mut vm = VM::with_runtime(runtime);
        match vm.execute_module(&compile_result.module) {
            Ok(result) => {
                println!("✅ VM execution completed successfully!");
                if let Some(func) = compile_result.module.functions.get("main") {
                    use nyash_rust::mir::MirType;
                    use nyash_rust::box_trait::{NyashBox, IntegerBox, BoolBox, StringBox};
                    use nyash_rust::boxes::FloatBox;
                    let (ety, sval) = match &func.signature.return_type {
                        MirType::Float => {
                            if let Some(fb) = result.as_any().downcast_ref::<FloatBox>() {
                                ("Float", format!("{}", fb.value))
                            } else if let Some(ib) = result.as_any().downcast_ref::<IntegerBox>() {
                                ("Float", format!("{}", ib.value as f64))
                            } else { ("Float", result.to_string_box().value) }
                        }
                        MirType::Integer => {
                            if let Some(ib) = result.as_any().downcast_ref::<IntegerBox>() {
                                ("Integer", ib.value.to_string())
                            } else { ("Integer", result.to_string_box().value) }
                        }
                        MirType::Bool => {
                            if let Some(bb) = result.as_any().downcast_ref::<BoolBox>() {
                                ("Bool", bb.value.to_string())
                            } else if let Some(ib) = result.as_any().downcast_ref::<IntegerBox>() {
                                ("Bool", (ib.value != 0).to_string())
                            } else { ("Bool", result.to_string_box().value) }
                        }
                        MirType::String => {
                            if let Some(sb) = result.as_any().downcast_ref::<StringBox>() {
                                ("String", sb.value.clone())
                            } else { ("String", result.to_string_box().value) }
                        }
                        _ => { (result.type_name(), result.to_string_box().value) }
                    };
                    println!("ResultType(MIR): {}", ety);
                    println!("Result: {}", sval);
                } else {
                    println!("Result: {:?}", result);
                }
            },
            Err(e) => {
                eprintln!("❌ VM execution error: {}", e);
                process::exit(1);
            }
        }
    }

    

    /// Collect Box declarations (moved to modes/vm.rs)
    #[cfg(any())]
    fn collect_box_declarations(&self, ast: &ASTNode, runtime: &NyashRuntime) {
        fn walk(node: &ASTNode, runtime: &NyashRuntime) {
            match node {
                ASTNode::Program { statements, .. } => {
                    for st in statements { walk(st, runtime); }
                }
                ASTNode::FunctionDeclaration { body, .. } => {
                    // Walk into function bodies to find nested box declarations
                    for st in body { walk(st, runtime); }
                }
                ASTNode::BoxDeclaration { name, fields, public_fields, private_fields, methods, constructors, init_fields, weak_fields, is_interface, extends, implements, type_parameters, .. } => {
                    // Walk into methods/constructors to find nested box declarations
                    for (_mname, mnode) in methods {
                        walk(mnode, runtime);
                    }
                    for (_ckey, cnode) in constructors {
                        walk(cnode, runtime);
                    }
                    let decl = CoreBoxDecl {
                        name: name.clone(),
                        fields: fields.clone(),
                        public_fields: public_fields.clone(),
                        private_fields: private_fields.clone(),
                        methods: methods.clone(),
                        constructors: constructors.clone(),
                        init_fields: init_fields.clone(),
                        weak_fields: weak_fields.clone(),
                        is_interface: *is_interface,
                        extends: extends.clone(),
                        implements: implements.clone(),
                        type_parameters: type_parameters.clone(),
                    };
                    if let Ok(mut map) = runtime.box_declarations.write() {
                        map.insert(name.clone(), decl);
                    }
                }
                _ => {}
            }
        }
        walk(ast, runtime);
    }

    // execute_wasm_mode moved to runner::modes::wasm

    // execute_aot_mode moved to runner::modes::aot

    /// Execute LLVM mode (moved to modes/llvm.rs)
    #[cfg(any())]
    fn execute_llvm_mode(&self, filename: &str) {
        // Read the file
        let code = match fs::read_to_string(filename) {
            Ok(content) => content,
            Err(e) => {
                eprintln!("❌ Error reading file {}: {}", filename, e);
                process::exit(1);
            }
        };

        // Parse to AST
        let ast = match NyashParser::parse_from_string(&code) {
            Ok(ast) => ast,
            Err(e) => {
                eprintln!("❌ Parse error: {}", e);
                process::exit(1);
            }
        };

        // Compile to MIR
        let mut mir_compiler = MirCompiler::new();
        let compile_result = match mir_compiler.compile(ast) {
            Ok(result) => result,
            Err(e) => {
                eprintln!("❌ MIR compilation error: {}", e);
                process::exit(1);
            }
        };

        println!("📊 MIR Module compiled successfully!");
        println!("📊 Functions: {}", compile_result.module.functions.len());

        // Execute via LLVM backend (mock implementation)
        #[cfg(feature = "llvm")]
        {
            let temp_path = "nyash_llvm_temp";
            match llvm_compile_and_execute(&compile_result.module, temp_path) {
                Ok(result) => {
                    if let Some(int_result) = result.as_any().downcast_ref::<IntegerBox>() {
                        let exit_code = int_result.value;
                        println!("✅ LLVM execution completed!");
                        println!("📊 Exit code: {}", exit_code);
                        
                        // Exit with the same code for testing
                        process::exit(exit_code as i32);
                    } else {
                        println!("✅ LLVM execution completed (non-integer result)!");
                        println!("📊 Result: {}", result.to_string_box().value);
                    }
                },
                Err(e) => {
                    eprintln!("❌ LLVM execution error: {}", e);
                    process::exit(1);
                }
            }
        }
        #[cfg(not(feature = "llvm"))]
        {
            // Mock implementation for demonstration
            println!("🔧 Mock LLVM Backend Execution:");
            println!("   This demonstrates the LLVM backend integration structure.");
            println!("   For actual LLVM compilation, build with --features llvm");
            println!("   and ensure LLVM 17+ development libraries are installed.");
            
            // Analyze the MIR to provide a meaningful mock result
            if let Some(main_func) = compile_result.module.functions.get("Main.main") {
                for (_block_id, block) in &main_func.blocks {
                    for inst in &block.instructions {
                        match inst {
                            MirInstruction::Return { value: Some(_) } => {
                                println!("   📊 Found return instruction - would generate LLVM return 42");
                                println!("✅ Mock LLVM execution completed!");
                                println!("📊 Mock exit code: 42");
                                process::exit(42);
                            }
                            MirInstruction::Return { value: None } => {
                                println!("   📊 Found void return - would generate LLVM return 0");
                                println!("✅ Mock LLVM execution completed!");
                                println!("📊 Mock exit code: 0");
                                process::exit(0);
                            }
                            _ => {}
                        }
                    }
                }
            }
            
            println!("✅ Mock LLVM execution completed!");
            println!("📊 Mock exit code: 0");
            process::exit(0);
        }
    }

    /// Execute benchmark mode (moved to modes/bench.rs)
    #[cfg(any())]
    fn execute_benchmark_mode(&self) {
        println!("🏁 Running benchmark mode with {} iterations", self.config.iterations);
        
        // Simple benchmark test file
        let test_code = r#"
        local x
        x = 42
        local y 
        y = x + 58
        return y
        "#;

        println!("\n🧪 Test code:");
        println!("{}", test_code);
        
        // Benchmark interpreter
        println!("\n⚡ Interpreter Backend:");
        let start = std::time::Instant::now();
        for _ in 0..self.config.iterations {
            if let Ok(ast) = NyashParser::parse_from_string(test_code) {
                let mut interpreter = NyashInterpreter::new_with_groups(BuiltinGroups::native_full());
                let _ = interpreter.execute(ast);
            }
        }
        let interpreter_time = start.elapsed();
        println!("  {} iterations in {:?} ({:.2} ops/sec)", 
            self.config.iterations, interpreter_time, 
            self.config.iterations as f64 / interpreter_time.as_secs_f64());

        // Benchmark VM if available
        println!("\n🚀 VM Backend:");
        let start = std::time::Instant::now();
        for _ in 0..self.config.iterations {
            if let Ok(ast) = NyashParser::parse_from_string(test_code) {
                let mut mir_compiler = MirCompiler::new();
                if let Ok(compile_result) = mir_compiler.compile(ast) {
                    let mut vm = VM::new();
                    let _ = vm.execute_module(&compile_result.module);
                }
            }
        }
        let vm_time = start.elapsed();
        println!("  {} iterations in {:?} ({:.2} ops/sec)", 
            self.config.iterations, vm_time, 
            self.config.iterations as f64 / vm_time.as_secs_f64());

        // Performance comparison
        let speedup = interpreter_time.as_secs_f64() / vm_time.as_secs_f64();
        println!("\n📊 Performance Summary:");
        println!("  VM is {:.2}x {} than Interpreter", 
            if speedup > 1.0 { speedup } else { 1.0 / speedup },
            if speedup > 1.0 { "faster" } else { "slower" });
    }
}

impl NyashRunner {
    /// Run a file through independent JIT engine (no VM execute loop)
    fn run_file_jit_direct(&self, filename: &str) {
        use std::fs;
        use nyash_rust::{parser::NyashParser, mir::MirCompiler};
        // Small helper for unified error output (text or JSON)
        let emit_err = |phase: &str, code: &str, msg: &str| {
            if std::env::var("NYASH_JIT_STATS_JSON").ok().as_deref() == Some("1")
                || std::env::var("NYASH_JIT_ERROR_JSON").ok().as_deref() == Some("1") {
                let payload = serde_json::json!({
                    "kind": "jit_direct_error",
                    "phase": phase,
                    "code": code,
                    "message": msg,
                    "file": filename,
                });
                println!("{}", payload.to_string());
            } else {
                eprintln!("[JIT-direct][{}][{}] {}", phase, code, msg);
            }
        };
        // Require cranelift feature at runtime by attempting compile; if unavailable compile_function returns None
        let code = match fs::read_to_string(filename) {
            Ok(s) => s,
            Err(e) => { emit_err("read_file", "IO", &format!("{}", e)); std::process::exit(1); }
        };
        let ast = match NyashParser::parse_from_string(&code) {
            Ok(a) => a, Err(e) => { emit_err("parse", "SYNTAX", &format!("{}", e)); std::process::exit(1); }
        };
        let mut mc = MirCompiler::new();
        let cr = match mc.compile(ast) { Ok(m) => m, Err(e) => { emit_err("mir", "MIR_COMPILE", &format!("{}", e)); std::process::exit(1); } };
        let func = match cr.module.functions.get("main") { Some(f) => f, None => { emit_err("mir", "NO_MAIN", "No main function found"); std::process::exit(1); } };

        // Guard: refuse write-effects in jit-direct when policy.read_only
        {
            use nyash_rust::mir::MirInstruction;
            use nyash_rust::mir::effect::Effect;
            let policy = nyash_rust::jit::policy::current();
            let mut writes = 0usize;
            for (_bbid, bb) in func.blocks.iter() {
                for inst in bb.instructions.iter() {
                    let mask = inst.effects();
                    if mask.contains(Effect::WriteHeap) {
                        writes += 1;
                    }
                }
                if let Some(term) = &bb.terminator {
                    if term.effects().contains(Effect::WriteHeap) { writes += 1; }
                }
            }
            if policy.read_only && writes > 0 {
                emit_err("policy", "WRITE_EFFECTS", &format!("write-effects detected ({} ops). jit-direct is read-only at this stage.", writes));
                std::process::exit(1);
            }
        }

        // jit-direct 安定化: 分岐合流(PHI)は明示ブロック引数で配線
        {
            let mut cfg = nyash_rust::jit::config::current();
            cfg.phi_min = true; // enable multi-PHI arg passing/join
            nyash_rust::jit::config::set_current(cfg);
        }
        // Prepare minimal runtime hooks so JIT externs (checkpoint/await) can reach GC/scheduler
        {
            let rt = nyash_rust::runtime::NyashRuntime::new();
            nyash_rust::runtime::global_hooks::set_from_runtime(&rt);
        }
        let mut engine = nyash_rust::jit::engine::JitEngine::new();
        match engine.compile_function("main", func) {
            Some(h) => {
                // Optional event: compile
                nyash_rust::jit::events::emit("compile", &func.signature.name, Some(h), None, serde_json::json!({}));
                // Parse JIT args from env: NYASH_JIT_ARGS (comma-separated), with optional type prefixes
                // Formats per arg: i:123, f:3.14, b:true/false, h:42 (handle), or bare numbers (int), true/false (bool)
                let mut jit_args: Vec<nyash_rust::jit::abi::JitValue> = Vec::new();
                if let Ok(s) = std::env::var("NYASH_JIT_ARGS") {
                    for raw in s.split(',') {
                        let t = raw.trim();
                        if t.is_empty() { continue; }
                        let v = if let Some(rest) = t.strip_prefix("i:") {
                            rest.parse::<i64>().ok().map(nyash_rust::jit::abi::JitValue::I64)
                        } else if let Some(rest) = t.strip_prefix("f:") {
                            rest.parse::<f64>().ok().map(nyash_rust::jit::abi::JitValue::F64)
                        } else if let Some(rest) = t.strip_prefix("b:") {
                            let b = matches!(rest, "1"|"true"|"True"|"TRUE");
                            Some(nyash_rust::jit::abi::JitValue::Bool(b))
                        } else if let Some(rest) = t.strip_prefix("h:") {
                            rest.parse::<u64>().ok().map(nyash_rust::jit::abi::JitValue::Handle)
                        } else if t.eq_ignore_ascii_case("true") || t == "1" { Some(nyash_rust::jit::abi::JitValue::Bool(true)) }
                          else if t.eq_ignore_ascii_case("false") || t == "0" { Some(nyash_rust::jit::abi::JitValue::Bool(false)) }
                          else if let Ok(iv) = t.parse::<i64>() { Some(nyash_rust::jit::abi::JitValue::I64(iv)) }
                          else if let Ok(fv) = t.parse::<f64>() { Some(nyash_rust::jit::abi::JitValue::F64(fv)) }
                          else { None };
                        if let Some(jv) = v { jit_args.push(jv); }
                    }
                }
                // Coerce args to expected MIR types
                use nyash_rust::mir::MirType;
                let expected = &func.signature.params;
                if expected.len() != jit_args.len() {
                    emit_err("args", "COUNT_MISMATCH", &format!("expected={}, passed={}", expected.len(), jit_args.len()));
                    eprintln!("Hint: set NYASH_JIT_ARGS as comma-separated values, e.g., i:42,f:3.14,b:true");
                    std::process::exit(1);
                }
                let mut coerced: Vec<nyash_rust::jit::abi::JitValue> = Vec::with_capacity(jit_args.len());
                for (i, (exp, got)) in expected.iter().zip(jit_args.iter()).enumerate() {
                    let cv = match exp {
                        MirType::Integer => match got {
                            nyash_rust::jit::abi::JitValue::I64(v) => nyash_rust::jit::abi::JitValue::I64(*v),
                            nyash_rust::jit::abi::JitValue::F64(f) => nyash_rust::jit::abi::JitValue::I64(*f as i64),
                            nyash_rust::jit::abi::JitValue::Bool(b) => nyash_rust::jit::abi::JitValue::I64(if *b {1} else {0}),
                            _ => { emit_err("args", "TYPE_MISMATCH", &format!("param#{} expects Integer", i)); std::process::exit(1); }
                        },
                        MirType::Float => match got {
                            nyash_rust::jit::abi::JitValue::F64(f) => nyash_rust::jit::abi::JitValue::F64(*f),
                            nyash_rust::jit::abi::JitValue::I64(v) => nyash_rust::jit::abi::JitValue::F64(*v as f64),
                            nyash_rust::jit::abi::JitValue::Bool(b) => nyash_rust::jit::abi::JitValue::F64(if *b {1.0} else {0.0}),
                            _ => { emit_err("args", "TYPE_MISMATCH", &format!("param#{} expects Float", i)); std::process::exit(1); }
                        },
                        MirType::Bool => match got {
                            nyash_rust::jit::abi::JitValue::Bool(b) => nyash_rust::jit::abi::JitValue::Bool(*b),
                            nyash_rust::jit::abi::JitValue::I64(v) => nyash_rust::jit::abi::JitValue::Bool(*v != 0),
                            nyash_rust::jit::abi::JitValue::F64(f) => nyash_rust::jit::abi::JitValue::Bool(*f != 0.0),
                            _ => { emit_err("args", "TYPE_MISMATCH", &format!("param#{} expects Bool", i)); std::process::exit(1); }
                        },
                        MirType::String | MirType::Box(_) | MirType::Array(_) | MirType::Future(_) => match got {
                            nyash_rust::jit::abi::JitValue::Handle(h) => nyash_rust::jit::abi::JitValue::Handle(*h),
                            _ => { emit_err("args", "TYPE_MISMATCH", &format!("param#{} expects handle (h:<id>)", i)); std::process::exit(1); }
                        },
                        MirType::Void | MirType::Unknown => {
                            // Keep as-is
                            *got
                        }
                    };
                    coerced.push(cv);
                }
                nyash_rust::jit::rt::set_current_jit_args(&coerced);
                let t0 = std::time::Instant::now();
                let out = engine.execute_handle(h, &coerced);
                match out {
                    Some(v) => {
                        let ms = t0.elapsed().as_millis();
                        nyash_rust::jit::events::emit("execute", &func.signature.name, Some(h), Some(ms), serde_json::json!({}));
                        // Normalize result according to MIR return type for friendly output
                        use nyash_rust::mir::MirType;
                        let ret_ty = &func.signature.return_type;
                        let vmv = match (ret_ty, v) {
                            (MirType::Bool, nyash_rust::jit::abi::JitValue::I64(i)) => nyash_rust::backend::vm::VMValue::Bool(i != 0),
                            (MirType::Bool, nyash_rust::jit::abi::JitValue::Bool(b)) => nyash_rust::backend::vm::VMValue::Bool(b),
                            (MirType::Float, nyash_rust::jit::abi::JitValue::F64(f)) => nyash_rust::backend::vm::VMValue::Float(f),
                            (MirType::Float, nyash_rust::jit::abi::JitValue::I64(i)) => nyash_rust::backend::vm::VMValue::Float(i as f64),
                            // Default adapter for other combos
                            _ => nyash_rust::jit::abi::adapter::from_jit_value(v),
                        };
                        println!("✅ JIT-direct execution completed successfully!");
                        // Pretty print with expected type tag
                        let (ety, sval) = match (ret_ty, &vmv) {
                            (MirType::Bool, nyash_rust::backend::vm::VMValue::Bool(b)) => ("Bool", b.to_string()),
                            (MirType::Float, nyash_rust::backend::vm::VMValue::Float(f)) => ("Float", format!("{}", f)),
                            (MirType::Integer, nyash_rust::backend::vm::VMValue::Integer(i)) => ("Integer", i.to_string()),
                            // Fallbacks
                            (_, nyash_rust::backend::vm::VMValue::Integer(i)) => ("Integer", i.to_string()),
                            (_, nyash_rust::backend::vm::VMValue::Float(f)) => ("Float", format!("{}", f)),
                            (_, nyash_rust::backend::vm::VMValue::Bool(b)) => ("Bool", b.to_string()),
                            (_, nyash_rust::backend::vm::VMValue::String(s)) => ("String", s.clone()),
                            (_, nyash_rust::backend::vm::VMValue::BoxRef(arc)) => ("BoxRef", arc.type_name().to_string()),
                            (_, nyash_rust::backend::vm::VMValue::Future(_)) => ("Future", "<future>".to_string()),
                            (_, nyash_rust::backend::vm::VMValue::Void) => ("Void", "void".to_string()),
                        };
                        println!("ResultType(MIR): {}", ety);
                        println!("Result: {}", sval);
                        // Optional JSON stats
                        if std::env::var("NYASH_JIT_STATS_JSON").ok().as_deref() == Some("1") {
                            let cfg = nyash_rust::jit::config::current();
                            let caps = nyash_rust::jit::config::probe_capabilities();
                            let (phi_t, phi_b1, ret_b) = engine.last_lower_stats();
                            let abi_mode = if cfg.native_bool_abi && caps.supports_b1_sig { "b1_bool" } else { "i64_bool" };
                            let payload = serde_json::json!({
                                "version": 1,
                                "function": func.signature.name,
                                "abi_mode": abi_mode,
                                "abi_b1_enabled": cfg.native_bool_abi,
                                "abi_b1_supported": caps.supports_b1_sig,
                                "b1_norm_count": nyash_rust::jit::rt::b1_norm_get(),
                                "ret_bool_hint_count": nyash_rust::jit::rt::ret_bool_hint_get(),
                                "phi_total_slots": phi_t,
                                "phi_b1_slots": phi_b1,
                                "ret_bool_hint_used": ret_b,
                            });
                            println!("{}", payload.to_string());
                        }
                    }
                    None => {
                        nyash_rust::jit::events::emit("fallback", &func.signature.name, Some(h), None, serde_json::json!({"reason":"trap_or_missing"}));
                        emit_err("execute", "TRAP_OR_MISSING", "execution failed (trap or missing handle)");
                        std::process::exit(1);
                    }
                }
            }
            None => {
                emit_err("compile", "UNAVAILABLE", "Build with --features cranelift-jit");
                std::process::exit(1);
            }
        }
    }
}

// Demo functions (moved from main.rs)
// moved to demos.rs

// moved to demos.rs

// moved to demos.rs

// moved to demos.rs

// moved to demos.rs

// moved to demos.rs
