use crate::config::env::{joinir_dev_enabled, joinir_strict_enabled};
use crate::mir::join_ir::{lower_funcscanner_trim_to_joinir, lower_skip_ws_to_joinir, JoinFuncId};
use crate::mir::join_ir_ops::JoinValue;
use crate::mir::join_ir_vm_bridge::run_joinir_via_vm;
use crate::mir::MirModule;
use crate::runtime::get_global_ring0;
use std::process;

/// Main.skip/1 用 JoinIR ブリッジ（Exec: JoinIR→VM 実行まで対応）
///
/// Note: PHI canary として使用しているため、default_enabled=false。
/// env フラグ（NYASH_JOINIR_EXPERIMENT=1 & NYASH_JOINIR_VM_BRIDGE=1）が必須。
pub(crate) fn try_run_skip_ws(module: &MirModule, quiet_pipe: bool) -> bool {
    eprintln!("[joinir/vm_bridge] Attempting JoinIR path for Main.skip");

    let Some(join_module) = lower_skip_ws_to_joinir(module) else {
        eprintln!("[joinir/vm_bridge] lower_skip_ws_to_joinir returned None");
        eprintln!("[joinir/vm_bridge] Falling back to normal VM path");
        return false;
    };

    // 入力引数を取得（環境変数またはデフォルト）
    let input = std::env::var("NYASH_JOINIR_INPUT").unwrap_or_else(|_| "   abc".to_string());
    eprintln!("[joinir/vm_bridge] Input: {:?}", input);

    let dev_bridge =
        joinir_dev_enabled() || std::env::var("NYASH_EMIT_MIR_TRACE").ok().as_deref() == Some("1");
    let strict = joinir_strict_enabled();

    match run_joinir_via_vm(&join_module, JoinFuncId::new(0), &[JoinValue::Str(input)]) {
        Ok(result) => {
            let exit_code = match &result {
                JoinValue::Int(v) => *v as i32,
                JoinValue::Bool(b) => {
                    if *b {
                        1
                    } else {
                        0
                    }
                }
                _ => 0,
            };
            eprintln!("[joinir/vm_bridge] ✅ JoinIR result: {:?}", result);
            if dev_bridge {
                // Devモード: 結果を出しても exit しない（後続パスを継続して観測する）
                if !quiet_pipe {
                    println!("RC: {}", exit_code);
                }
                return true;
            } else if strict {
                if !quiet_pipe {
                    println!("RC: {}", exit_code);
                }
                process::exit(exit_code);
            } else {
                if !quiet_pipe {
                    println!("RC: {}", exit_code);
                }
                process::exit(exit_code);
            }
        }
        Err(e) => {
            eprintln!("[joinir/vm_bridge] ❌ JoinIR execution failed: {:?}", e);
            eprintln!("[joinir/vm_bridge] Falling back to normal VM path");
            false
        }
    }
}

/// FuncScannerBox.trim/1 用 JoinIR ブリッジ（Exec: JoinIR→VM 実行まで対応）
///
/// A/B 実証済み、事実上本線。default_enabled=true で env フラグなしでも有効。
pub(crate) fn try_run_trim(module: &MirModule, quiet_pipe: bool) -> bool {
    eprintln!("[joinir/vm_bridge] Attempting JoinIR path for FuncScannerBox.trim");

    let Some(join_module) = lower_funcscanner_trim_to_joinir(module) else {
        eprintln!("[joinir/vm_bridge] lower_funcscanner_trim_to_joinir returned None");
        eprintln!("[joinir/vm_bridge] Falling back to normal VM path");
        return false;
    };

    // 入力引数を取得（環境変数またはデフォルト）
    let input = std::env::var("NYASH_JOINIR_INPUT").unwrap_or_else(|_| "   abc  ".to_string());
    eprintln!("[joinir/vm_bridge] Input: {:?}", input);

    let dev_bridge =
        joinir_dev_enabled() || std::env::var("NYASH_EMIT_MIR_TRACE").ok().as_deref() == Some("1");
    let strict = joinir_strict_enabled();

    match run_joinir_via_vm(&join_module, JoinFuncId::new(0), &[JoinValue::Str(input)]) {
        Ok(result) => {
            eprintln!("[joinir/vm_bridge] ✅ JoinIR trim result: {:?}", result);
            if dev_bridge {
                if !quiet_pipe {
                    match &result {
                        JoinValue::Str(s) => println!("{}", s),
                        _ => println!("{:?}", result),
                    }
                }
                return true;
            } else if strict {
                if !quiet_pipe {
                    match &result {
                        JoinValue::Str(s) => println!("{}", s),
                        _ => println!("{:?}", result),
                    }
                }
                process::exit(0);
            } else {
                if !quiet_pipe {
                    match &result {
                        JoinValue::Str(s) => println!("{}", s),
                        _ => println!("{:?}", result),
                    }
                }
                process::exit(0);
            }
        }
        Err(e) => {
            eprintln!("[joinir/vm_bridge] ❌ JoinIR trim failed: {:?}", e);
            eprintln!("[joinir/vm_bridge] Falling back to normal VM path");
            false
        }
    }
}

// ============================================================================
// Phase 82: Exec routes 統一ヘルパー（重複ロジック排除）
// ============================================================================

/// JoinIR 実行ルートの統一ヘルパー
///
/// `try_run_skip_ws()` と `try_run_trim()` の共通パターンを吸収。
///
/// # Phase 82 SSOT 統一
/// 現在は後方互換性のため既存関数を保持。
/// 将来のフェーズで try_run_skip_ws/try_run_trim を このヘルパーで統合可能。
///
/// # Arguments
/// - `lowerer`: JoinIR に lowering する関数（返り値 Option<JoinModule>）
/// - `input_val`: 入力値（JoinValue形式）
/// - `output_formatter`: 出力値を文字列に変換する関数
/// - `exit_code_extractor`: 出力値から終了コードを抽出する関数
/// - `route_name`: ログ出力用の名前（例: "Main.skip", "FuncScannerBox.trim"）
#[allow(dead_code)]
fn run_generic_joinir_route<F, G, H>(
    lowerer: F,
    input_val: JoinValue,
    output_formatter: G,
    exit_code_extractor: H,
    route_name: &str,
    quiet_pipe: bool,
) -> bool
where
    F: FnOnce() -> Option<crate::mir::join_ir::JoinModule>,
    G: Fn(&JoinValue) -> String,
    H: Fn(&JoinValue) -> i32,
{
    get_global_ring0().log.info(&format!(
        "[joinir/vm_bridge] Attempting JoinIR path for {}",
        route_name
    ));

    let Some(join_module) = lowerer() else {
        get_global_ring0().log.info(&format!(
            "[joinir/vm_bridge] lower_{} returned None",
            route_name.replace(".", "_").to_lowercase()
        ));
        get_global_ring0()
            .log
            .info("[joinir/vm_bridge] Falling back to normal VM path");
        return false;
    };

    let dev_bridge =
        joinir_dev_enabled() || std::env::var("NYASH_EMIT_MIR_TRACE").ok().as_deref() == Some("1");
    let strict = joinir_strict_enabled();

    match run_joinir_via_vm(&join_module, JoinFuncId::new(0), &[input_val]) {
        Ok(result) => {
            get_global_ring0().log.info(&format!(
                "[joinir/vm_bridge] ✅ JoinIR result: {:?}",
                result
            ));
            let output = output_formatter(&result);
            let exit_code = exit_code_extractor(&result);

            if dev_bridge {
                if !quiet_pipe {
                    println!("{}", output);
                }
                return true;
            } else if strict {
                if !quiet_pipe {
                    println!("{}", output);
                }
                process::exit(exit_code);
            } else {
                if !quiet_pipe {
                    println!("{}", output);
                }
                process::exit(exit_code);
            }
        }
        Err(e) => {
            get_global_ring0().log.info(&format!(
                "[joinir/vm_bridge] ❌ JoinIR {} failed: {:?}",
                route_name, e
            ));
            get_global_ring0()
                .log
                .info("[joinir/vm_bridge] Falling back to normal VM path");
            false
        }
    }
}
