//! Phase 33-22: JoinIR Conversion Pipeline
//!
//! Unifies the conversion flow: JoinIR → MIR → Merge
//!
//! ## Responsibility
//!
//! - Convert JoinModule to MirModule
//! - Merge MirModule blocks into current function
//! - Handle boundary mapping and exit PHI generation
//!
//! ## Usage
//!
//! ```rust
//! let exit_phi_result = JoinIRConversionPipeline::execute(
//!     builder,
//!     join_module,
//!     Some(&boundary),
//!     "pattern1",
//!     debug,
//! )?;
//! ```
//!
//! ## Benefits
//!
//! - **Single conversion path**: All patterns use same JoinIR→MIR→Merge flow
//! - **Consistent error handling**: Unified error messages
//! - **Testability**: Can test conversion independently
//! - **Reduces duplication**: Eliminates 120 lines across Pattern 1-4

use crate::mir::builder::MirBuilder;
use crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary;
use crate::mir::join_ir::JoinModule;
use crate::mir::ValueId;
use std::collections::BTreeMap;

pub(crate) struct JoinIRConversionPipeline;

impl JoinIRConversionPipeline {
    /// Execute unified conversion pipeline
    ///
    /// Flow: JoinModule → MirModule → merge_joinir_mir_blocks
    ///
    /// # Arguments
    ///
    /// - `builder`: MirBuilder instance for merging blocks
    /// - `join_module`: JoinIR module to convert
    /// - `boundary`: Optional boundary mapping for input/output values
    /// - `pattern_name`: Name for debug messages (e.g., "pattern1", "pattern2")
    /// - `debug`: Enable debug output
    ///
    /// # Returns
    ///
    /// - `Ok(Some(ValueId))`: Exit PHI result if boundary has exit bindings
    /// - `Ok(None)`: No exit PHI generated (simple loops)
    /// - `Err(String)`: Conversion or merge failure
    ///
    /// # Example
    ///
    /// ```rust
    /// // Pattern 1: Simple loop (no exit PHI)
    /// let _ = JoinIRConversionPipeline::execute(
    ///     builder,
    ///     join_module,
    ///     Some(&boundary),
    ///     "pattern1",
    ///     false,
    /// )?;
    ///
    /// // Pattern 3: Loop with carriers (exit PHI generated)
    /// let exit_phi = JoinIRConversionPipeline::execute(
    ///     builder,
    ///     join_module,
    ///     Some(&boundary),
    ///     "pattern3",
    ///     true,
    /// )?;
    /// ```
    pub fn execute(
        builder: &mut MirBuilder,
        join_module: JoinModule,
        boundary: Option<&JoinInlineBoundary>,
        pattern_name: &str,
        debug: bool,
    ) -> Result<Option<ValueId>, String> {
        use super::super::trace;
        use crate::mir::join_ir::frontend::JoinFuncMetaMap;
        use crate::mir::join_ir_vm_bridge::bridge_joinir_to_mir_with_meta;

        // Step 1: Log JoinIR stats (functions and blocks)
        trace::trace().joinir_stats(
            pattern_name,
            join_module.functions.len(),
            join_module.functions.values().map(|f| f.body.len()).sum(),
        );

        // Step 2: JoinModule → MirModule conversion
        // Pass empty meta map since minimal lowerers don't use metadata
        let empty_meta: JoinFuncMetaMap = BTreeMap::new();
        let mir_module = bridge_joinir_to_mir_with_meta(&join_module, &empty_meta)
            .map_err(|e| format!("[{}/pipeline] MIR conversion failed: {:?}", pattern_name, e))?;

        // Step 3: Log MIR stats (functions and blocks)
        trace::trace().joinir_stats(
            pattern_name,
            mir_module.functions.len(),
            mir_module.functions.values().map(|f| f.blocks.len()).sum(),
        );

        // Step 4: Merge into current function
        let exit_phi_result = builder.merge_joinir_mir_blocks(&mir_module, boundary, debug)?;

        Ok(exit_phi_result)
    }
}
