use crate::ast::ASTNode;
use crate::mir::builder::MirBuilder;
use crate::mir::join_ir::lowering::carrier_info::CarrierInfo;
use crate::mir::join_ir::lowering::condition_env::ConditionEnv;
use crate::mir::join_ir::lowering::condition_lowering_box::{
    ConditionContext, ConditionLoweringBox,
};
use crate::mir::join_ir::lowering::debug_output_box::DebugOutputBox;
use crate::mir::join_ir::lowering::error_tags;
use crate::mir::join_ir::lowering::expr_lowerer::{ExprContext, ExprLowerer};
use crate::mir::join_ir::lowering::loop_body_local_env::LoopBodyLocalEnv;
use crate::mir::join_ir::lowering::scope_manager::Pattern2ScopeManager;
use crate::mir::join_ir::JoinInst;
use crate::mir::loop_pattern_detection::function_scope_capture::CapturedEnv;
use crate::mir::ValueId;

fn make_scope_manager<'a>(
    condition_env: &'a ConditionEnv,
    body_local_env: Option<&'a LoopBodyLocalEnv>,
    captured_env: Option<&'a CapturedEnv>,
    carrier_info: &'a CarrierInfo,
) -> Pattern2ScopeManager<'a> {
    Pattern2ScopeManager {
        condition_env,
        loop_body_local_env: body_local_env,
        captured_env,
        carrier_info,
    }
}

pub(crate) fn lower_header_condition(
    condition: &ASTNode,
    env: &ConditionEnv,
    carrier_info: &CarrierInfo,
    loop_var_name: &str,
    loop_var_id: ValueId,
    alloc_value: &mut dyn FnMut() -> ValueId,
    current_static_box_name: Option<&str>,
    debug: &DebugOutputBox,
) -> Result<(ValueId, Vec<JoinInst>), String> {
    let empty_body_env = LoopBodyLocalEnv::new();
    let empty_captured_env = CapturedEnv::new();
    let scope_manager = make_scope_manager(
        env,
        Some(&empty_body_env),
        Some(&empty_captured_env),
        carrier_info,
    );

    if !ExprLowerer::<Pattern2ScopeManager>::is_supported_condition(condition) {
        return Err(error_tags::lowering_error(
            "pattern4/condition",
            "ConditionLoweringBox does not support this condition (legacy path removed)",
        ));
    }

    let mut dummy_builder = MirBuilder::new();
    let mut expr_lowerer =
        ExprLowerer::new(&scope_manager, ExprContext::Condition, &mut dummy_builder);

    let mut context = ConditionContext {
        loop_var_name: loop_var_name.to_string(),
        loop_var_id,
        scope: &scope_manager,
        alloc_value,
        current_static_box_name: current_static_box_name.map(|s| s.to_string()),
    };

    let value_id = expr_lowerer.lower_condition(condition, &mut context).map_err(|e| {
        format!(
            "[joinir/pattern4/phase244] ConditionLoweringBox failed on supported condition: {:?}",
            e
        )
    })?;

    let instructions = expr_lowerer.take_last_instructions();
    debug.log(
        "phase244",
        &format!(
            "Header condition via ConditionLoweringBox: {} instructions",
            instructions.len()
        ),
    );

    Ok((value_id, instructions))
}
