//! Phase 33-21: Pattern 4 (Loop with Continue) Implementation
//!
//! **Current Status**: Fully implemented using Select-based continue semantics.
//!
//! ## Implementation Approach
//!
//! Continue is handled via Select instruction for carrier updates:
//! - When continue condition is true: carrier keeps its value (no update)
//! - When continue condition is false: carrier gets updated value
//!
//! This avoids the complexity of explicit latch blocks by using PHI-based
//! value selection at each iteration.
//!
//! ## Example
//!
//! ```nyash
//! local i = 0
//! local sum = 0
//! loop(i < 10) {
//!   i = i + 1
//!   if i % 2 == 0 { continue }  // Skip even numbers
//!   sum = sum + i
//! }
//! // sum = 25 (1+3+5+7+9)
//! ```
//!
//! ## Key Implementation Details
//!
//! - **Select instruction**: Used to conditionally skip carrier updates
//! - **Header PHI**: Tracks carrier values across iterations
//! - **ExitMeta**: Maps final carrier values to host variable slots
//! - **Phase 33-21 fix**: Correct remapping of function parameters to header PHI dsts

use super::super::trace;
use crate::ast::ASTNode;
use crate::mir::builder::MirBuilder;
use crate::mir::join_ir::lowering::loop_update_analyzer::UpdateExpr;
use crate::mir::loop_pattern_detection::error_messages;
use crate::mir::ValueId;
use std::collections::BTreeMap;

// Phase 284 P1: has_return_in_body/has_return_node removed
// Return detection now handled by return_collector SSOT in conversion_pipeline.rs

/// Phase 282 P6: Detection function for Pattern 4 (ExtractionBased)
///
/// Migrated from StructureBased to ExtractionBased detection model.
/// Uses pure extractor (extract_loop_with_continue_parts) for SSOT.
///
/// Pattern 4 matches loops with continue statements.
///
/// # ExtractionBased Detection (Phase 282 P6)
///
/// Two-stage guard:
/// 1. **Safety valve**: ctx.pattern_kind == Pattern4Continue (O(1) perf guard)
/// 2. **Extractor**: extract_loop_with_continue_parts (SSOT)
///
/// # Detection Rules (from extractor)
///
/// 1. **Condition**: Comparison operator with left=variable (Pattern1 reuse)
/// 2. **Must have continue**: At least 1 continue statement (recursive detection)
/// 3. **No break**: break statements → Pattern2 territory
/// 4. **No return**: return statements → Err (close-but-unsupported, Phase 142 P2 pending)
/// 5. **Carrier validation**: Delegated to CommonPatternInitializer (existing logic)
///
/// If all conditions are met, Pattern 4 is detected.
pub(crate) fn can_lower(builder: &MirBuilder, ctx: &super::router::LoopPatternContext) -> bool {
    use super::common_init::CommonPatternInitializer;
    use crate::mir::loop_pattern_detection::LoopPatternKind;

    // Phase 282 P6 Step 1: Pattern kind safety valve (O(1) guard)
    if ctx.pattern_kind != LoopPatternKind::Pattern4Continue {
        return false;
    }

    // Phase 282 P6 Step 2: ExtractionBased detection (SSOT)
    use super::extractors::pattern4::extract_loop_with_continue_parts;

    match extract_loop_with_continue_parts(ctx.condition, ctx.body) {
        Ok(Some(parts)) => {
            trace::trace().debug(
                "pattern4/can_lower",
                &format!(
                    "✅ Pattern4 detected: loop_var='{}', continue_count={}",
                    parts.loop_var, parts.continue_count
                ),
            );

            // Phase 282 P6 Step 3: Carrier validation (existing logic preserved)
            CommonPatternInitializer::check_carrier_updates_allowed(
                ctx.body,
                &parts.loop_var,
                &builder.variable_ctx.variable_map,
            )
        }
        Ok(None) => {
            trace::trace().debug(
                "pattern4/can_lower",
                "Not Pattern4 (extraction returned None - structural mismatch)",
            );
            false
        }
        Err(e) => {
            // USER CORRECTION: Log "unsupported" for Err cases (e.g., return found)
            trace::trace().debug(
                "pattern4/can_lower",
                &format!("Pattern4 unsupported: {}", e),
            );
            false
        }
    }
}

/// Phase 282 P6: Lowering function for Pattern 4 (ExtractionBased)
///
/// Re-extracts pattern parts to enforce SSOT (extraction is single source of truth).
/// Wrapper around cf_loop_pattern4_with_continue to match router signature.
///
/// # Implementation (Phase 195-197 + Phase 282 P6)
///
/// 1. Re-extract pattern parts (SSOT enforcement - Phase 282 P6)
/// 2. Extract loop variables from condition
/// 3. Generate JoinIR with continue support (lower_loop_with_continue_minimal)
/// 4. Convert JoinModule → MirModule
/// 5. Create JoinInlineBoundary for input/output mapping
/// 6. Merge MIR blocks into current_function
/// 7. Return loop result (first carrier value)
pub(crate) fn lower(
    builder: &mut MirBuilder,
    ctx: &super::router::LoopPatternContext,
) -> Result<Option<ValueId>, String> {
    // Phase 282 P6 Step 4: Re-extract to enforce SSOT (extraction must succeed in lower())
    use super::extractors::pattern4::extract_loop_with_continue_parts;

    let parts = match extract_loop_with_continue_parts(ctx.condition, ctx.body) {
        Ok(Some(p)) => p,
        Ok(None) => {
            return Err(
                "[pattern4/lower] Extraction returned None (should not happen - can_lower() passed)"
                    .to_string(),
            );
        }
        Err(e) => {
            // USER CORRECTION: Return Err directly for fail-fast (e.g., return found)
            return Err(format!("[pattern4/lower] Extraction failed: {}", e));
        }
    };

    trace::trace().debug(
        "pattern4/lower",
        &format!(
            "Pattern4 lowering: loop_var='{}', continue_count={}",
            parts.loop_var, parts.continue_count
        ),
    );

    // Phase 284 P1: Return check removed - now handled by return_collector SSOT
    // in conversion_pipeline.rs (JoinIR line common entry point)

    // Phase 33-19: Connect to actual implementation (zero behavior change)
    builder.cf_loop_pattern4_with_continue(ctx.condition, ctx.body, ctx.func_name, ctx.debug)
}

impl MirBuilder {
    /// Phase 179-B: Pattern 4 (Loop with Continue) lowerer
    ///
    /// **Refactored**: Now uses PatternPipelineContext for unified preprocessing
    ///
    /// # Pipeline (Phase 179-B)
    /// 1. Build preprocessing context → PatternPipelineContext
    /// 2. Pattern 4-specific processing (continue normalization, carrier analysis)
    /// 3. Call JoinIR lowerer → JoinModule
    /// 4. Create boundary from context → JoinInlineBoundary
    /// 5. Merge MIR blocks → JoinIRConversionPipeline
    ///
    /// # Example
    ///
    /// ```nyash
    /// local i = 0
    /// local sum = 0
    /// loop(i < 10) {
    ///   i = i + 1
    ///   if (i % 2 == 0) {
    ///     continue  // Skip even numbers
    ///   }
    ///   sum = sum + i
    /// }
    /// // sum = 25 (1+3+5+7+9)
    /// ```
    ///
    /// Note: Pattern 4 has complex carrier analysis logic that remains inline
    /// for now, using Pattern4CarrierAnalyzer for Select-based continue semantics.
    pub(in crate::mir::builder) fn cf_loop_pattern4_with_continue(
        &mut self,
        condition: &ASTNode,
        _body: &[ASTNode],
        _func_name: &str,
        debug: bool,
    ) -> Result<Option<ValueId>, String> {
        // Phase 195: Use unified trace
        trace::trace().debug("pattern4", "Calling Pattern 4 minimal lowerer");

        let prepared = prepare_pattern4_context(self, condition, _body)?;
        lower_pattern4_joinir(self, condition, &prepared, debug)
    }
}

/// Preprocessed data for Pattern 4 lowering.
struct Pattern4Prepared<'a> {
    loop_var_name: String,
    loop_scope: crate::mir::join_ir::lowering::loop_scope_shape::LoopScopeShape,
    carrier_info: crate::mir::join_ir::lowering::carrier_info::CarrierInfo,
    carrier_updates: BTreeMap<String, UpdateExpr>,
    /// Phase 284 P1: Reference to loop body for return detection
    body: &'a [ASTNode],
}

/// Normalize, build context, analyze carriers, and promote loop-body locals.
fn prepare_pattern4_context<'a>(
    builder: &mut MirBuilder,
    condition: &ASTNode,
    body: &'a [ASTNode],
) -> Result<Pattern4Prepared<'a>, String> {
    use super::pattern4_carrier_analyzer::Pattern4CarrierAnalyzer;
    use super::pattern_pipeline::{build_pattern_context, PatternVariant};
    use crate::mir::loop_pattern_detection::loop_body_cond_promoter::{
        ConditionPromotionRequest, ConditionPromotionResult, LoopBodyCondPromoter,
    };
    use crate::mir::loop_pattern_detection::loop_condition_scope::LoopConditionScopeBox;

    // Normalize continue branches for analysis/lowering
    let normalized_body = Pattern4CarrierAnalyzer::normalize_continue_branches(body);

    // Build preprocessing context
    let ctx = build_pattern_context(
        builder,
        condition,
        &normalized_body,
        PatternVariant::Pattern4,
    )?;

    let loop_var_name = ctx.loop_var_name.clone();
    let loop_scope = ctx.loop_scope.clone();
    let carrier_info_prelim = ctx.carrier_info.clone();

    // Analyze carrier updates and filter carriers
    let carrier_updates = Pattern4CarrierAnalyzer::analyze_carrier_updates(
        &normalized_body,
        &carrier_info_prelim.carriers,
    );
    let mut carrier_info =
        Pattern4CarrierAnalyzer::analyze_carriers(&normalized_body, &carrier_info_prelim)?;

    trace::trace().debug(
        "pattern4",
        &format!(
            "CarrierInfo: loop_var={}, carriers={:?}",
            carrier_info.loop_var_name,
            carrier_info
                .carriers
                .iter()
                .map(|c| &c.name)
                .collect::<Vec<_>>()
        ),
    );

    trace::trace().debug(
        "pattern4",
        &format!(
            "Analyzed {} carrier update expressions",
            carrier_updates.len()
        ),
    );
    for (carrier_name, update_expr) in &carrier_updates {
        trace::trace().debug(
            "pattern4",
            &format!("  {} → {:?}", carrier_name, update_expr),
        );
    }

    // LoopBodyLocal promotion for conditions (skip_whitespace etc.)
    let continue_cond = LoopBodyCondPromoter::extract_continue_condition(&normalized_body);
    let conditions_to_analyze: Vec<&ASTNode> = if let Some(cont_cond) = continue_cond {
        vec![condition, cont_cond]
    } else {
        vec![condition]
    };

    let cond_scope =
        LoopConditionScopeBox::analyze(&loop_var_name, &conditions_to_analyze, Some(&loop_scope));

    if cond_scope.has_loop_body_local() {
        let promotion_req = ConditionPromotionRequest {
            loop_param_name: &loop_var_name,
            cond_scope: &cond_scope,
            scope_shape: Some(&loop_scope),
            break_cond: None, // Pattern 4 has no break
            continue_cond,
            loop_body: &normalized_body,
            #[cfg(feature = "normalized_dev")]
            // Phase 136 Step 4/7: Use binding_ctx for binding_map reference
            binding_map: Some(builder.binding_ctx.binding_map()),
        };

        match LoopBodyCondPromoter::try_promote_for_condition(promotion_req) {
            ConditionPromotionResult::Promoted {
                carrier_info: promoted_carrier,
                promoted_var,
                carrier_name,
            } => {
                trace::trace().debug(
                    "pattern4/cond_promoter",
                    &format!(
                        "LoopBodyLocal '{}' promoted to carrier '{}'",
                        promoted_var, carrier_name
                    ),
                );

                #[cfg(feature = "normalized_dev")]
                {
                    use crate::mir::join_ir::lowering::carrier_binding_assigner::CarrierBindingAssigner;
                    let mut promoted_carrier = promoted_carrier;
                    CarrierBindingAssigner::assign_promoted_binding(
                        builder,
                        &mut promoted_carrier,
                        &promoted_var,
                        &carrier_name,
                    )
                    .map_err(|e| format!("[phase78/binding_assign] {:?}", e))?;
                    carrier_info.merge_from(&promoted_carrier);
                }
                #[cfg(not(feature = "normalized_dev"))]
                {
                    carrier_info.merge_from(&promoted_carrier);
                }

                trace::trace().debug(
                    "pattern4/cond_promoter",
                    &format!(
                        "Merged carrier '{}' into CarrierInfo (total carriers: {})",
                        carrier_name,
                        carrier_info.carrier_count()
                    ),
                );

                if let Some(helper) = carrier_info.trim_helper() {
                    if helper.is_safe_trim() {
                        trace::trace().debug(
                            "pattern4/cond_promoter",
                            "Safe Trim/skip_whitespace pattern detected",
                        );
                        trace::trace().debug(
                            "pattern4/cond_promoter",
                            &format!(
                                "Carrier: '{}', original var: '{}', whitespace chars: {:?}",
                                helper.carrier_name, helper.original_var, helper.whitespace_chars
                            ),
                        );
                    } else {
                        return Err(error_messages::format_error_pattern4_trim_not_safe(
                            &helper.carrier_name,
                            helper.whitespace_count(),
                        ));
                    }
                }
            }
            ConditionPromotionResult::CannotPromote { reason, vars } => {
                return Err(error_messages::format_error_pattern4_promotion_failed(
                    &vars, &reason,
                ));
            }
        }
    }

    Ok(Pattern4Prepared {
        loop_var_name,
        loop_scope,
        carrier_info,
        carrier_updates,
        body, // Phase 284 P1: Include body for return detection
    })
}

/// JoinIR lowering stage for Pattern 4 using prepared context.
fn lower_pattern4_joinir(
    builder: &mut MirBuilder,
    condition: &ASTNode,
    prepared: &Pattern4Prepared<'_>,
    debug: bool,
) -> Result<Option<ValueId>, String> {
    use super::super::merge::exit_line::meta_collector::ExitMetaCollector;
    use super::conversion_pipeline::JoinIRConversionPipeline;
    use crate::mir::join_ir::lowering::join_value_space::JoinValueSpace;
    use crate::mir::join_ir::lowering::loop_with_continue_minimal::lower_loop_with_continue_minimal;
    use crate::mir::join_ir::lowering::return_collector::{collect_return_from_body, ReturnInfo};
    use crate::mir::join_ir::lowering::JoinInlineBoundaryBuilder;

    trace::trace().varmap("pattern4_start", &builder.variable_ctx.variable_map);

    // Phase 284 P1: Detect return statements in body
    let return_info: Option<ReturnInfo> = match collect_return_from_body(prepared.body) {
        Ok(info) => info,
        Err(e) => {
            return Err(format!("[pattern4] Return detection failed: {}", e));
        }
    };

    if let Some(ref ret_info) = return_info {
        trace::trace().debug(
            "pattern4",
            &format!(
                "Phase 284 P1: Return detected - value={}, has_condition={}, in_else={}",
                ret_info.value,
                ret_info.condition.is_some(),
                ret_info.in_else
            ),
        );
    }

    let mut join_value_space = JoinValueSpace::new();

    #[cfg(feature = "normalized_dev")]
    // Phase 136 Step 4/7: Use binding_ctx for binding_map clone
    let binding_map_clone = builder.binding_ctx.binding_map().clone();

    let (join_module, exit_meta) = match lower_loop_with_continue_minimal(
        prepared.loop_scope.clone(),
        condition,
        builder,
        &prepared.carrier_info,
        &prepared.carrier_updates,
        &mut join_value_space,
        return_info.as_ref(), // Phase 284 P1
        #[cfg(feature = "normalized_dev")]
        Some(&binding_map_clone),
    ) {
        Ok(result) => result,
        Err(e) => {
            trace::trace().debug("pattern4", &format!("Pattern 4 lowerer failed: {}", e));
            return Err(error_messages::format_error_pattern4_lowering_failed(&e));
        }
    };

    trace::trace().debug(
        "pattern4",
        &format!("ExitMeta: {} exit bindings", exit_meta.exit_values.len()),
    );
    for (carrier_name, join_value) in &exit_meta.exit_values {
        trace::trace().debug(
            "pattern4",
            &format!("  {} → ValueId({})", carrier_name, join_value.0),
        );
    }

    let exit_bindings = ExitMetaCollector::collect(
        builder,
        &exit_meta,
        Some(&prepared.carrier_info), // Phase 228-8: Include ConditionOnly carriers
        debug,
    );

    for carrier in &prepared.carrier_info.carriers {
        if !exit_bindings.iter().any(|b| b.carrier_name == carrier.name) {
            return Err(error_messages::format_error_pattern4_carrier_not_found(
                &carrier.name,
            ));
        }
    }

    // Phase 256.8.5: Use JoinModule.entry.params as SSOT (no hardcoded ValueIds)
    use super::common::get_entry_function;
    let main_func = get_entry_function(&join_module, "pattern4")?;

    // SSOT: Use actual params allocated by JoinIR lowerer
    let join_inputs = main_func.params.clone();

    // Build host_inputs in same order (loop_var + carriers)
    let mut host_inputs = vec![prepared.carrier_info.loop_var_id];
    for carrier in &prepared.carrier_info.carriers {
        host_inputs.push(carrier.host_id);
    }

    // Verify count consistency (fail-fast)
    if join_inputs.len() != host_inputs.len() {
        return Err(format!(
            "[pattern4] Params count mismatch: join_inputs={}, host_inputs={}",
            join_inputs.len(), host_inputs.len()
        ));
    }

    trace::trace().debug(
        "pattern4",
        &format!(
            "join_inputs (SSOT): {:?}, host_inputs: {:?}",
            join_inputs.iter().map(|v| v.0).collect::<Vec<_>>(),
            host_inputs.iter().map(|v| v.0).collect::<Vec<_>>()
        ),
    );

    // Phase 284 P1: Build continuation set - include k_return if return_info exists
    let continuation_funcs = {
        use crate::mir::join_ir::lowering::canonical_names as cn;
        let mut funcs = std::collections::BTreeSet::new();
        funcs.insert(cn::K_EXIT.to_string());
        if return_info.is_some() {
            funcs.insert(cn::K_RETURN.to_string());
        }
        funcs
    };

    let boundary = JoinInlineBoundaryBuilder::new()
        .with_inputs(join_inputs, host_inputs) // Dynamic carrier count
        .with_exit_bindings(exit_bindings)
        .with_loop_var_name(Some(prepared.loop_var_name.clone()))
        .with_carrier_info(prepared.carrier_info.clone())
        .with_continuation_funcs(continuation_funcs) // Phase 284 P1
        .build();

    let _result_val = JoinIRConversionPipeline::execute(
        builder,
        join_module,
        Some(&boundary),
        "pattern4",
        debug,
    )?;

    let void_val = crate::mir::builder::emission::constant::emit_void(builder);
    trace::trace().debug(
        "pattern4",
        &format!("Loop complete, returning Void {:?}", void_val),
    );

    Ok(Some(void_val))
}
