//! Phase P3: LoopFrontendBinding - 関数名 → LoopPattern 変換層
//!
//! ## 責務（1行で表現）
//! **関数名から適切な LoopPattern を決定し、loop_patterns 層にディスパッチする**
//!
//! ## この層の責務
//!
//! - 関数名（"simple", "filter" 等）から `LoopPattern` enum を決定
//! - Break/Continue の有無を検出してパターンを調整
//! - `loop_patterns::lower_loop_with_pattern()` に委譲
//!
//! ## やらないこと
//!
//! - JSON body の詳細解析（それは loop_patterns 層）
//! - Box 名・メソッド名での判定（それは Bridge/VM 層）
//!
//! ## 設計原則
//!
//! ChatGPT 推奨の責務分離:
//! ```
//! LoopFrontendBinding → 関数名ベースの判定
//! loop_patterns       → LoopPattern enum での lowering
//! Bridge/VM           → Box 名・メソッド名での最適化
//! ```

use super::loop_patterns::{self, LoopPattern};
use super::{AstToJoinIrLowerer, JoinModule};

/// 関数名から LoopPattern を検出
///
/// # Arguments
/// * `func_name` - 関数名
/// * `loop_body` - Loop body の JSON（Break/Continue 検出用）
///
/// # Returns
/// 検出された LoopPattern
pub fn detect_loop_pattern(
    func_name: &str,
    loop_body: Option<&[serde_json::Value]>,
) -> LoopPattern {
    // Phase P3: 関数名ベースの判定
    // 将来的には Box 名やアノテーションも考慮可能
    match func_name {
        // Phase 55: PrintTokens パターン
        "print_tokens" => LoopPattern::PrintTokens,

        // Phase 56: Filter パターン
        "filter" => LoopPattern::Filter,

        // Phase 57+: Map パターン（未実装）
        "map" => LoopPattern::Map,

        // Phase 58+: Reduce パターン（未実装）
        "reduce" | "fold" => LoopPattern::Reduce,

        // Phase 90: ParseStringComposite パターン（dev-only by name）
        #[cfg(feature = "normalized_dev")]
        "parse_string_composite_minimal" => LoopPattern::ParseStringComposite,

        // デフォルト: Simple パターン
        // ただし Break/Continue/Return があれば別パターン
        _ => {
            if let Some(body) = loop_body {
                let has_break = AstToJoinIrLowerer::has_break_in_loop_body(body);
                let has_continue = AstToJoinIrLowerer::has_continue_in_loop_body(body);
                let has_return = AstToJoinIrLowerer::has_return_in_loop_body(body);

                // Phase 89: Continue + Return の複合パターン
                if has_continue && has_return {
                    LoopPattern::ContinueReturn
                } else if has_break {
                    LoopPattern::Break
                } else if has_continue {
                    LoopPattern::Continue
                } else {
                    LoopPattern::Simple
                }
            } else {
                LoopPattern::Simple
            }
        }
    }
}

/// ループパターンに基づいて lowering を実行
///
/// 関数名から LoopPattern を決定し、適切な lowering を実行する。
///
/// # Arguments
/// * `lowerer` - AstToJoinIrLowerer インスタンス
/// * `program_json` - Program(JSON v0)
///
/// # Returns
/// JoinModule または panic（未対応パターン）
pub fn lower_loop_by_function_name(
    lowerer: &mut AstToJoinIrLowerer,
    program_json: &serde_json::Value,
) -> JoinModule {
    // 1. 関数名を取得
    let defs = program_json["defs"]
        .as_array()
        .expect("Program(JSON v0) must have 'defs' array");

    let func_def = defs
        .get(0)
        .expect("At least one function definition required");

    let func_name = func_def["name"]
        .as_str()
        .expect("Function must have 'name'");

    // 2. Loop body を取得（Break/Continue 検出用）
    let body = &func_def["body"]["body"];
    let stmts = body.as_array().expect("Function body must be array");

    let loop_body: Option<&[serde_json::Value]> = stmts
        .iter()
        .find(|stmt| stmt["type"].as_str() == Some("Loop"))
        .and_then(|loop_node| loop_node["body"].as_array())
        .map(|v| v.as_slice());

    // 3. LoopPattern を決定（Break/Continue も新モジュールで処理）
    let pattern = detect_loop_pattern(func_name, loop_body);

    // 4. loop_patterns 層に委譲
    match loop_patterns::lower_loop_with_pattern(pattern.clone(), lowerer, program_json) {
        Ok(module) => module,
        Err(e) => panic!("LoopFrontendBinding error: {:?}", e),
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_detect_loop_pattern_by_name() {
        assert_eq!(detect_loop_pattern("filter", None), LoopPattern::Filter);
        assert_eq!(
            detect_loop_pattern("print_tokens", None),
            LoopPattern::PrintTokens
        );
        assert_eq!(detect_loop_pattern("map", None), LoopPattern::Map);
        assert_eq!(detect_loop_pattern("reduce", None), LoopPattern::Reduce);
        assert_eq!(detect_loop_pattern("simple", None), LoopPattern::Simple);
        assert_eq!(detect_loop_pattern("unknown", None), LoopPattern::Simple);
    }
}
