use super::*;

// VM dispatch trace macro (used across handlers)
macro_rules! trace_dispatch {
    ($method:expr, $handler:expr) => {
        if $method == "length" && std::env::var("NYASH_VM_TRACE").ok().as_deref() == Some("1") {
            eprintln!("[vm-trace] length dispatch handler={}", $handler);
        }
    };
}

mod arithmetic;
mod boxes;
mod boxes_array;
mod boxes_instance;
mod boxes_map;
mod boxes_object_fields;
mod boxes_plugin;
mod boxes_string;
mod boxes_void_guards;
mod calls;
mod extern_provider;
mod externals;
mod lifecycle;
mod memory;
mod misc;
mod string_method_helpers;
mod type_ops;
mod weak; // Phase 285A0: WeakRef handlers

impl MirInterpreter {
    pub(super) fn execute_instruction(&mut self, inst: &MirInstruction) -> Result<(), VMError> {
        match inst {
            MirInstruction::Const { dst, value } => self.handle_const(*dst, value)?,
            MirInstruction::NewBox {
                dst,
                box_type,
                args,
            } => self.handle_new_box(*dst, box_type, args)?,
            MirInstruction::PluginInvoke {
                dst,
                box_val,
                method,
                args,
                ..
            } => self.handle_plugin_invoke(*dst, *box_val, method, args)?,
            MirInstruction::BoxCall {
                dst,
                box_val,
                method,
                args,
                ..
            } => self.handle_box_call(*dst, *box_val, method, args)?,
            MirInstruction::ExternCall {
                dst,
                iface_name,
                method_name,
                args,
                ..
            } => self.handle_extern_call(*dst, iface_name, method_name, args)?,
            MirInstruction::RefSet {
                reference,
                field,
                value,
            } => self.handle_ref_set(*reference, field, *value)?,
            MirInstruction::RefGet {
                dst,
                reference,
                field,
            } => self.handle_ref_get(*dst, *reference, field)?,
            MirInstruction::BinOp { dst, op, lhs, rhs } => {
                self.handle_binop(*dst, *op, *lhs, *rhs)?
            }
            MirInstruction::UnaryOp { dst, op, operand } => {
                self.handle_unary_op(*dst, *op, *operand)?
            }
            MirInstruction::Compare { dst, op, lhs, rhs } => {
                self.handle_compare(*dst, *op, *lhs, *rhs)?
            }
            MirInstruction::TypeOp { dst, op, value, ty } => {
                self.handle_type_op(*dst, *op, *value, ty)?
            }
            MirInstruction::Copy { dst, src } => self.handle_copy(*dst, *src)?,
            MirInstruction::Load { dst, ptr } => self.handle_load(*dst, *ptr)?,
            MirInstruction::Store { ptr, value } => self.handle_store(*ptr, *value)?,
            MirInstruction::Call {
                dst,
                func,
                callee,
                args,
                ..
            } => self.handle_call(*dst, *func, callee.as_ref(), args)?,
            MirInstruction::Debug { message, value } => {
                self.handle_debug(message, *value)?;
            }
            MirInstruction::DebugLog { message, values } => {
                // Dev-only: MIR-level debug logging (no new values defined).
                if std::env::var("NYASH_MIR_DEBUG_LOG").ok().as_deref() == Some("1") {
                    eprint!("[MIR-LOG] {}:", message);
                    for vid in values {
                        let v = self.reg_load(*vid).unwrap_or(VMValue::Void);
                        eprint!(" %{}={:?}", vid.0, v);
                    }
                    eprintln!();
                }
            }
            MirInstruction::Print { value, .. } => self.handle_print(*value)?,
            // Phase 256 P1.5: Select instruction (ternary conditional)
            MirInstruction::Select {
                dst,
                cond,
                then_val,
                else_val,
            } => {
                let cond_val = self.reg_load(*cond)?;
                let is_true = cond_val.as_bool()?;
                let selected_val = if is_true {
                    self.reg_load(*then_val)?
                } else {
                    self.reg_load(*else_val)?
                };
                self.regs.insert(*dst, selected_val);
            }
            // Phase 285A0: WeakRef handlers (delegated to weak.rs)
            MirInstruction::WeakNew { dst, box_val } => {
                self.handle_weak_new(*dst, *box_val)?;
            }
            MirInstruction::WeakLoad { dst, weak_ref } => {
                self.handle_weak_load(*dst, *weak_ref)?;
            }
            MirInstruction::WeakRef { dst, op, value } => match op {
                WeakRefOp::New => self.handle_weak_new(*dst, *value)?,
                WeakRefOp::Load => self.handle_weak_load(*dst, *value)?,
            }
            MirInstruction::BarrierRead { .. }
            | MirInstruction::BarrierWrite { .. }
            | MirInstruction::Barrier { .. }
            | MirInstruction::Safepoint => {}
            // Phase 287: Lifecycle management
            MirInstruction::KeepAlive { .. } => {
                // No-op: KeepAlive only affects DCE/liveness analysis
            }
            MirInstruction::ReleaseStrong { values } => {
                self.release_strong_refs(values);
            }
            MirInstruction::Nop => {}
            other => {
                return Err(self.err_invalid(format!(
                    "MIR interp: unimplemented instruction: {:?}",
                    other
                )))
            }
        }
        Ok(())
    }
}
