use super::{BasicBlockId, ValueId};
use crate::ast::{ASTNode, LiteralValue};

impl super::MirBuilder {
    // Peek expression lowering
    pub(super) fn build_peek_expression(
        &mut self,
        scrutinee: ASTNode,
        arms: Vec<(LiteralValue, ASTNode)>,
        else_expr: ASTNode,
    ) -> Result<ValueId, String> {
        // Evaluate scrutinee in the current block
        let scr_val = self.build_expression_impl(scrutinee)?;

        // Prepare merge and result
        let merge_block: BasicBlockId = self.next_block_id();
        let result_val = self.next_value_id();
        let mut phi_inputs: Vec<(BasicBlockId, ValueId)> = Vec::new();

        // Create dispatch block where we start comparing arms
        let dispatch_block = self.next_block_id();
        // Jump from current block to dispatch (ensure terminator exists)
        let need_jump = {
            let cur = self.current_block;
            if let (Some(cb), Some(ref func)) = (cur, &self.scope_ctx.current_function) {
                if let Some(bb) = func.blocks.get(&cb) {
                    !bb.is_terminated()
                } else {
                    true
                }
            } else {
                true
            }
        };
        if need_jump {
            crate::mir::builder::emission::branch::emit_jump(self, dispatch_block)?;
        }
        self.start_new_block(dispatch_block)?;

        // If there are no arms, fall through to else directly
        if arms.is_empty() {
            let else_block = self.next_block_id();
            crate::mir::builder::emission::branch::emit_jump(self, else_block)?;
            self.start_new_block(else_block)?;
            let else_val = self.build_expression_impl(else_expr)?;
            phi_inputs.push((else_block, else_val));
            crate::mir::builder::emission::branch::emit_jump(self, merge_block)?;
            self.start_new_block(merge_block)?;
            // フェーズM: PHI はブロック先頭に配置（cf_common 統一）
            self.insert_phi_with_dst(result_val, phi_inputs)?;
            return Ok(result_val);
        }

        // Else block to handle default case
        let else_block = self.next_block_id();

        // Chain dispatch blocks for each arm
        let mut cur_dispatch = dispatch_block;
        for (i, (label, arm_expr)) in arms.iter().cloned().enumerate() {
            let then_block = self.next_block_id();
            // Next dispatch (only for non-last arm)
            let next_dispatch = if i + 1 < arms.len() {
                Some(self.next_block_id())
            } else {
                None
            };
            let else_target = next_dispatch.unwrap_or(else_block);

            // In current dispatch block, compare and branch
            self.start_new_block(cur_dispatch)?;
            let lit_id = match label {
                LiteralValue::String(s) => {
                    crate::mir::builder::emission::constant::emit_string(self, s)
                }
                LiteralValue::Integer(i) => {
                    crate::mir::builder::emission::constant::emit_integer(self, i)
                }
                LiteralValue::Bool(b) => {
                    crate::mir::builder::emission::constant::emit_bool(self, b)
                }
                LiteralValue::Float(f) => {
                    crate::mir::builder::emission::constant::emit_float(self, f)
                }
                LiteralValue::Null => crate::mir::builder::emission::constant::emit_null(self),
                LiteralValue::Void => crate::mir::builder::emission::constant::emit_void(self),
            };
            let cond_id = self.next_value_id();
            crate::mir::builder::emission::compare::emit_to(
                self,
                cond_id,
                super::CompareOp::Eq,
                scr_val,
                lit_id,
            )?;
            crate::mir::builder::emission::branch::emit_conditional(
                self,
                cond_id,
                then_block,
                else_target,
            )?;

            // then arm
            self.start_new_block(then_block)?;
            let then_val = self.build_expression_impl(arm_expr)?;
            phi_inputs.push((then_block, then_val));
            crate::mir::builder::emission::branch::emit_jump(self, merge_block)?;

            // Move to next dispatch or else block
            cur_dispatch = else_target;
        }

        // Lower else expression in else_block
        self.start_new_block(else_block)?;
        let else_val = self.build_expression_impl(else_expr)?;
        phi_inputs.push((else_block, else_val));
        crate::mir::builder::emission::branch::emit_jump(self, merge_block)?;

        // Merge and yield result
        self.start_new_block(merge_block)?;
        // フェーズM: PHI はブロック先頭に配置（cf_common 統一）
        if let (Some(func), Some(cur_bb)) =
            (self.scope_ctx.current_function.as_mut(), self.current_block)
        {
            crate::mir::ssot::cf_common::insert_phi_at_head_spanned(
                func,
                cur_bb,
                result_val,
                phi_inputs,
                self.metadata_ctx.current_span(),
            );
        } else {
            self.emit_instruction(super::MirInstruction::Phi {
                dst: result_val,
                inputs: phi_inputs,
                type_hint: None, // Phase 63-6: Legacy path, no type hint
            })?;
        }
        Ok(result_val)
    }
}
