/*!
 * Runner Pipe I/O helpers — JSON v0 handling
 *
 * Extracted from runner/mod.rs to keep the main runner slimmer.
 * Handles:
 *  - Reading JSON v0 from stdin or file
 *  - Optional MIR dump
 *  - Optional PyVM delegation via tools/pyvm_runner.py
 *  - Fallback to MIR interpreter execution
 */

use super::*;

impl NyashRunner {
    /// Try to handle `--ny-parser-pipe` / `--json-file` flow.
    /// Returns true if the request was handled (program should return early).
    pub(super) fn try_run_json_v0_pipe(&self) -> bool {
        let groups = self.config.as_groups();
        if !(groups.parser.ny_parser_pipe || groups.parser.json_file.is_some()) {
            return false;
        }
        let json = if let Some(path) = &groups.parser.json_file {
            match std::fs::read_to_string(path) {
                Ok(s) => s,
                Err(e) => {
                    eprintln!("❌ json-file read error: {}", e);
                    std::process::exit(1);
                }
            }
        } else {
            use std::io::Read;
            let mut buf = String::new();
            if let Err(e) = std::io::stdin().read_to_string(&mut buf) {
                eprintln!("❌ stdin read error: {}", e);
                std::process::exit(1);
            }
            buf
        };
        // Optional: convert Program(JSON v0) → MIR(JSON) and exit when requested
        if let Some(out) = &groups.emit.program_json_to_mir {
            match super::json_v0_bridge::parse_json_v0_to_module(&json) {
                Ok(module) => {
                    let p = std::path::Path::new(out);
                    if let Err(e) = super::mir_json_emit::emit_mir_json_for_harness_bin(&module, p)
                    {
                        eprintln!("❌ Program→MIR emit error: {}", e);
                        std::process::exit(1);
                    }
                    std::process::exit(0);
                }
                Err(e) => {
                    eprintln!("❌ Program(JSON v0) parse error: {}", e);
                    std::process::exit(1);
                }
            }
        }

        // Optional: delegate to PyVM when NYASH_PIPE_USE_PYVM=1
        if crate::config::env::pipe_use_pyvm() {
            let py = which::which("python3").ok();
            if let Some(py3) = py {
                let runner = std::path::Path::new("tools/pyvm_runner.py");
                if runner.exists() {
                    // We need a MIR module for PyVM: try v1 bridge first, then v0 parse
                    if let Ok(Some(module)) =
                        crate::runner::json_v1_bridge::try_parse_v1_to_module(&json)
                    {
                        super::json_v0_bridge::maybe_dump_mir(&module);
                        let tmp_dir = std::path::Path::new("tmp");
                        let _ = std::fs::create_dir_all(tmp_dir);
                        let mir_json_path = tmp_dir.join("nyash_pyvm_mir.json");
                        if let Err(e) = super::mir_json_emit::emit_mir_json_for_harness_bin(
                            &module,
                            &mir_json_path,
                        ) {
                            eprintln!("❌ PyVM MIR JSON emit error: {}", e);
                            std::process::exit(1);
                        }
                        crate::cli_v!("[Bridge] using PyVM (pipe) → {}", mir_json_path.display());
                        // Determine entry function
                        let allow_top = crate::config::env::entry_allow_toplevel_main();
                        let entry = if module.functions.contains_key("Main.main") {
                            "Main.main"
                        } else if allow_top && module.functions.contains_key("main") {
                            "main"
                        } else if module.functions.contains_key("main") {
                            eprintln!("[entry] Warning: using top-level 'main' without explicit allow; set NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN=1 to silence.");
                            "main"
                        } else {
                            "Main.main"
                        };
                        let mut cmd = std::process::Command::new(py3);
                        crate::runner::child_env::apply_core_wrapper_env(&mut cmd);
                        let status = cmd
                            .args([
                                runner.to_string_lossy().as_ref(),
                                "--in",
                                &mir_json_path.display().to_string(),
                                "--entry",
                                entry,
                            ])
                            .status()
                            .map_err(|e| format!("spawn pyvm: {}", e))
                            .unwrap();
                        let code = status.code().unwrap_or(1);
                        if !status.success() {
                            crate::cli_v!("❌ PyVM (pipe) failed (status={})", code);
                        }
                        std::process::exit(code);
                    }
                    // v0 fallback for PyVM
                    match super::json_v0_bridge::parse_json_v0_to_module(&json) {
                        Ok(module) => {
                            let tmp_dir = std::path::Path::new("tmp");
                            let _ = std::fs::create_dir_all(tmp_dir);
                            let mir_json_path = tmp_dir.join("nyash_pyvm_mir.json");
                            if let Err(e) = super::mir_json_emit::emit_mir_json_for_harness_bin(
                                &module,
                                &mir_json_path,
                            ) {
                                eprintln!("❌ PyVM MIR JSON emit error: {}", e);
                                std::process::exit(1);
                            }
                            crate::cli_v!(
                                "[Bridge] using PyVM (pipe, v0) → {}",
                                mir_json_path.display()
                            );
                            let mut cmd = std::process::Command::new(py3);
                            crate::runner::child_env::apply_core_wrapper_env(&mut cmd);
                            let status = cmd
                                .args([
                                    runner.to_string_lossy().as_ref(),
                                    "--in",
                                    &mir_json_path.display().to_string(),
                                ])
                                .status()
                                .map_err(|e| format!("spawn pyvm: {}", e))
                                .unwrap();
                            let code = status.code().unwrap_or(1);
                            if !status.success() {
                                crate::cli_v!("❌ PyVM (pipe,v0) failed (status={})", code);
                            }
                            std::process::exit(code);
                        }
                        Err(e) => {
                            eprintln!("❌ JSON parse error for PyVM path: {}", e);
                            std::process::exit(1);
                        }
                    }
                } else {
                    eprintln!("❌ PyVM runner not found: {}", runner.display());
                    std::process::exit(1);
                }
            } else {
                eprintln!("❌ python3 not found in PATH. Install Python 3 to use PyVM with --ny-parser-pipe.");
                std::process::exit(1);
            }
        }
        // Default/Unified: delegate to CoreExecutor (boxed)
        let rc = crate::runner::core_executor::run_json_v0(self, &json);
        std::process::exit(rc);
    }
}
