use crate::mir::join_ir::{BinOpKind, CompareOp, ConstValue, JoinModule, MirLikeInst};
use crate::mir::{
    BinaryOp, CompareOp as MirCompareOp, ConstValue as MirConstValue, EffectMask, MirInstruction,
    MirModule,
};

use super::JoinIrVmBridgeError;

// Phase 190: Use modular converters from parent module
use super::joinir_function_converter::JoinIrFunctionConverter;

/// Phase 190: JoinIR → MIR 変換器（統合エントリーポイント）
///
/// Phase 32 L-2.2 Step-3: テストから呼び出し可能に `pub(crate)` 化
#[cfg_attr(not(test), allow(dead_code))]
pub(crate) fn convert_joinir_to_mir(
    join_module: &JoinModule,
) -> Result<MirModule, JoinIrVmBridgeError> {
    // Phase 190: Delegate to FunctionConverter
    JoinIrFunctionConverter::convert_joinir_to_mir(join_module)
}

/// MirLikeInst → MirInstruction 変換
/// Phase 190: 共有ユーティリティとして pub(crate) に変更
pub(crate) fn convert_mir_like_inst(
    mir_like: &MirLikeInst,
) -> Result<MirInstruction, JoinIrVmBridgeError> {
    match mir_like {
        MirLikeInst::Const { dst, value } => {
            let mir_const = match value {
                ConstValue::Integer(i) => MirConstValue::Integer(*i),
                ConstValue::Bool(b) => MirConstValue::Bool(*b),
                ConstValue::String(s) => MirConstValue::String(s.clone()),
                ConstValue::Null => MirConstValue::Null,
            };
            Ok(MirInstruction::Const {
                dst: *dst,
                value: mir_const,
            })
        }
        MirLikeInst::BinOp { dst, op, lhs, rhs } => {
            let mir_op = match op {
                BinOpKind::Add => BinaryOp::Add,
                BinOpKind::Sub => BinaryOp::Sub,
                BinOpKind::Mul => BinaryOp::Mul,
                BinOpKind::Div => BinaryOp::Div,
                BinOpKind::Mod => BinaryOp::Mod, // Phase 188-Impl-3
                BinOpKind::Or => BinaryOp::Or,
                BinOpKind::And => BinaryOp::And,
            };
            Ok(MirInstruction::BinOp {
                dst: *dst,
                op: mir_op,
                lhs: *lhs,
                rhs: *rhs,
            })
        }
        MirLikeInst::Compare { dst, op, lhs, rhs } => {
            let mir_cmp = match op {
                CompareOp::Lt => MirCompareOp::Lt,
                CompareOp::Le => MirCompareOp::Le,
                CompareOp::Gt => MirCompareOp::Gt,
                CompareOp::Ge => MirCompareOp::Ge,
                CompareOp::Eq => MirCompareOp::Eq,
                CompareOp::Ne => MirCompareOp::Ne,
            };
            Ok(MirInstruction::Compare {
                dst: *dst,
                op: mir_cmp,
                lhs: *lhs,
                rhs: *rhs,
            })
        }
        MirLikeInst::BoxCall {
            dst,
            box_name,
            method,
            args,
        } => {
            // Phase 27-shortterm S-4.3: BoxCall → MIR BoxCall
            // box_name は JoinIR で保持しているが、MIR BoxCall には receiver ValueId のみ
            // 暫定: args[0] を receiver として扱う
            if args.is_empty() {
                return Err(JoinIrVmBridgeError::new(format!(
                    "BoxCall requires at least one argument (receiver), got: box_name={}, method={}",
                    box_name, method
                )));
            }

            let receiver = args[0];
            let method_args = args[1..].to_vec();

            Ok(MirInstruction::BoxCall {
                dst: *dst,
                box_val: receiver,
                method: method.clone(),
                method_id: None, // Phase 27-shortterm: no method ID resolution
                args: method_args,
                effects: EffectMask::PURE, // Phase 27-shortterm: assume pure
            })
        }
        // Phase 56: UnaryOp
        MirLikeInst::UnaryOp { dst, op, operand } => {
            let mir_op = match op {
                crate::mir::join_ir::UnaryOp::Not => crate::mir::types::UnaryOp::Not,
                crate::mir::join_ir::UnaryOp::Neg => crate::mir::types::UnaryOp::Neg,
            };
            Ok(MirInstruction::UnaryOp {
                dst: *dst,
                op: mir_op,
                operand: *operand,
            })
        }
        // Phase 188: Print
        MirLikeInst::Print { value } => Ok(MirInstruction::Print {
            value: *value,
            effects: EffectMask::IO,
        }),
        // Phase 188-Impl-3: Select
        // Select is a ternary operator: cond ? then_val : else_val
        // This should not be directly converted to a single MIR instruction
        // Instead, it should be handled by merge_joinir_mir_blocks which creates
        // proper control flow with branches and PHI nodes
        MirLikeInst::Select { .. } => {
            Err(JoinIrVmBridgeError::new(
                "Select instruction should be handled by merge_joinir_mir_blocks, not convert_mir_like_inst".to_string()
            ))
        }
    }
}
