//! JoinIR development / experimental flags (SSOT).
//! Phase 72-C: Consolidate all NYASH_JOINIR_* dev flags through centralized helpers.
//! Phase 45: JoinIR mode unification (StructuredOnly / NormalizedDev / NormalizedCanonical)

use crate::config::env::env_bool;

/// Phase 45: JoinIR execution mode enum
///
/// Centralizes all JoinIR routing decisions (Structured vs Normalized paths).
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum JoinIrMode {
    /// Default mode: Structured→MIR direct (no Normalized layer)
    StructuredOnly,

    /// Development mode: Structured→Normalized→MIR(direct) for supported shapes
    /// Requires `--features normalized_dev` + env var
    NormalizedDev,

    /// Future mode: All canonical shapes use Normalized→MIR(direct)
    /// Currently unused, reserved for Phase 46+ canonical migration
    NormalizedCanonical,
}

/// NYASH_JOINIR_LOWER_GENERIC=1 - Enable generic lowering path for JoinIR
/// (CRITICAL: 15 occurrences in codebase)
pub fn lower_generic_enabled() -> bool {
    env_bool("NYASH_JOINIR_LOWER_GENERIC")
}

/// NYASH_JOINIR_MAINLINE_DEBUG=1 - Debug output for mainline JoinIR lowering
pub fn mainline_debug_enabled() -> bool {
    env_bool("NYASH_JOINIR_MAINLINE_DEBUG")
}

/// NYASH_JOINIR_IF_MERGE=1 - Enable If-merge experimental mode
pub fn if_merge_enabled() -> bool {
    env_bool("NYASH_JOINIR_IF_MERGE")
}

/// NYASH_JOINIR_DEBUG=1 - General debug mode (deprecated, prefer mainline_debug)
pub fn debug_enabled() -> bool {
    env_bool("NYASH_JOINIR_DEBUG")
}

/// NYASH_JOINIR_VM_BRIDGE=1 - Enable VM bridge mode
pub fn vm_bridge_enabled() -> bool {
    env_bool("NYASH_JOINIR_VM_BRIDGE")
}

/// HAKO_JOINIR_STRICT=1 or NYASH_JOINIR_STRICT=1 - Strict validation mode
///
/// Phase 138-P2-A: Supports both HAKO_ and NYASH_ prefixes for compatibility
pub fn strict_enabled() -> bool {
    env_bool("HAKO_JOINIR_STRICT") || env_bool("NYASH_JOINIR_STRICT")
}

/// NYASH_JOINIR_SNAPSHOT_GENERATE=1 - Generate snapshot for testing
pub fn snapshot_generate_enabled() -> bool {
    env_bool("NYASH_JOINIR_SNAPSHOT_GENERATE")
}

/// NYASH_JOINIR_SNAPSHOT_TEST=1 - Test using snapshot
pub fn snapshot_test_enabled() -> bool {
    env_bool("NYASH_JOINIR_SNAPSHOT_TEST")
}

/// NYASH_JOINIR_INPUT=* - Input source or mode
pub fn input_mode() -> Option<String> {
    std::env::var("NYASH_JOINIR_INPUT").ok()
}

/// NYASH_JOINIR_LOWER_FROM_MIR=1 - Enable lowering from MIR mode
pub fn lower_from_mir_enabled() -> bool {
    env_bool("NYASH_JOINIR_LOWER_FROM_MIR")
}

/// NYASH_JOINIR_LLVM_EXPERIMENT=1 - LLVM experimental mode
pub fn llvm_experiment_enabled() -> bool {
    env_bool("NYASH_JOINIR_LLVM_EXPERIMENT")
}

/// HAKO_JOINIR_IF_TOPLEVEL=1 - Enable If-select for top-level if statements
pub fn if_toplevel_enabled() -> bool {
    env_bool("HAKO_JOINIR_IF_TOPLEVEL")
}

/// HAKO_JOINIR_IF_TOPLEVEL_TRACE=1 - Debug trace for top-level if
pub fn if_toplevel_trace_enabled() -> bool {
    env_bool("HAKO_JOINIR_IF_TOPLEVEL_TRACE")
}

/// HAKO_JOINIR_IF_IN_LOOP_TRACE=1 - Debug trace for if in loop
pub fn if_in_loop_trace_enabled() -> bool {
    env_bool("HAKO_JOINIR_IF_IN_LOOP_TRACE")
}

/// HAKO_JOINIR_NESTED_IF=1 - Enable nested if lowering
pub fn nested_if_enabled() -> bool {
    env_bool("HAKO_JOINIR_NESTED_IF")
}

/// HAKO_JOINIR_PRINT_TOKENS_MAIN=1 - Print tokens for main
pub fn print_tokens_main_enabled() -> bool {
    env_bool("HAKO_JOINIR_PRINT_TOKENS_MAIN")
}

/// HAKO_JOINIR_ARRAY_FILTER_MAIN=1 - Array filter main mode
pub fn array_filter_main_enabled() -> bool {
    env_bool("HAKO_JOINIR_ARRAY_FILTER_MAIN")
}

/// HAKO_JOINIR_READ_QUOTED=1 - Read quoted mode
pub fn read_quoted_enabled() -> bool {
    env_bool("HAKO_JOINIR_READ_QUOTED")
}

/// HAKO_JOINIR_READ_QUOTED_IFMERGE=1 - Read quoted with if-merge
pub fn read_quoted_ifmerge_enabled() -> bool {
    env_bool("HAKO_JOINIR_READ_QUOTED_IFMERGE")
}

/// NYASH_JOINIR_NORMALIZED_DEV_RUN=1 - Run JoinIR runner through Normalized roundtrip (dev only)
pub fn joinir_normalized_dev_run_enabled() -> bool {
    // Feature gate at call sites still applies; this helper just centralizes the env read.
    env_bool("NYASH_JOINIR_NORMALIZED_DEV_RUN")
}

/// Phase 45: Get current JoinIR execution mode
///
/// Determines routing based on feature flags and environment variables:
/// - `--features normalized_dev` + `NYASH_JOINIR_NORMALIZED_DEV_RUN=1` → NormalizedDev
/// - Otherwise → StructuredOnly
///
/// Note: NormalizedCanonical is reserved for future canonical migration (Phase 46+)
pub fn current_joinir_mode() -> JoinIrMode {
    #[cfg(feature = "normalized_dev")]
    {
        if joinir_normalized_dev_run_enabled() {
            JoinIrMode::NormalizedDev
        } else {
            JoinIrMode::StructuredOnly
        }
    }

    #[cfg(not(feature = "normalized_dev"))]
    {
        JoinIrMode::StructuredOnly
    }
}

/// Unified switch for Normalized dev experiments (feature + env).
///
/// - Requires `--features normalized_dev`
/// - Requires `NYASH_JOINIR_NORMALIZED_DEV_RUN=1`
///
/// Phase 45: Now implemented as a thin wrapper over current_joinir_mode()
pub fn normalized_dev_enabled() -> bool {
    matches!(current_joinir_mode(), JoinIrMode::NormalizedDev)
}

/// JOINIR_TEST_DEBUG=1 (or NYASH_JOINIR_TEST_DEBUG=1) - Verbose logging for normalized dev tests
pub fn joinir_test_debug_enabled() -> bool {
    env_bool("JOINIR_TEST_DEBUG") || env_bool("NYASH_JOINIR_TEST_DEBUG")
}

/// Phase 82: NYASH_PHI_FALLBACK_DISABLED=1 - Disable if_phi fallback (dev mode)
///
/// lifecycle.rs の infer_type_from_phi* callsite を封じて、
/// 実際に呼ばれているかどうかを確認するためのフラグ。
///
/// # 使用方法
///
/// ```bash
/// NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release mir_joinir_if_select
/// ```
///
/// # 期待される動作
///
/// - callsite が呼ばれる → panic (関数名・ValueId・Case を出力)
/// - callsite が一度も呼ばれない → テスト成功（削除候補確定）
///
/// # Case 分類
///
/// - **Case A**: P1/P2/P3-A/P3-B + hint 成功（hint 即座に返す）
/// - **Case B**: P1/P2/P3-A/P3-B + hint 失敗（PHI 走査）
/// - **Case D**: P3-C + GenericTypeResolver 失敗（PHI 走査・無駄な再実行）
///
/// Phase 84-5: if_phi.rs 削除後は常に true
/// 環境変数は統計目的でのみ残す
pub fn phi_fallback_disabled() -> bool {
    true // Phase 84-5: Always disabled after if_phi.rs deletion
}

/// Phase 84-5: 統計・メトリクス用（オプション）
#[allow(dead_code)]
pub fn phi_metrics_enabled() -> bool {
    env_bool("NYASH_PHI_METRICS")
}

/// Phase 183: NYASH_LEGACY_LOOPBUILDER=1 - Legacy LoopBuilder 経路を明示的に opt-in
///
/// デフォルトはJoinIR優先。どうしても古いLoopBuilder経路を使う必要がある場合のみ設定。
/// 本線では使用しない開発専用フラグ。
pub fn legacy_loopbuilder_enabled() -> bool {
    env_bool("NYASH_LEGACY_LOOPBUILDER")
}

/// Phase 145 P0: HAKO_ANF_DEV=1 - ANF (A-Normal Form) transformation development mode
///
/// Enables ANF transformation routing in NormalizedExprLowererBox.
/// P0: Debug logging only (execute_box is stub, returns Ok(None)).
/// P1+: Actual transformation (String.length() hoist, compound expression ANF).
///
/// # Usage
///
/// ```bash
/// HAKO_ANF_DEV=1 cargo test --release
/// HAKO_ANF_DEV=1 ./target/release/hakorune program.hako
/// ```
///
/// # Expected Behavior (P0)
///
/// - ANF routing enabled: AnfPlanBox detects impure expressions
/// - Debug log: "[phase145/debug] ANF plan found but execute returned None (P0 stub)"
/// - Existing behavior unchanged: execute_box returns Ok(None) → fallback to legacy
///
/// # Future Behavior (P1+)
///
/// - String.length() hoist: `x + s.length()` → ANF transformation
/// - Compound expression ANF: Recursive left-to-right linearization
pub fn anf_dev_enabled() -> bool {
    env_bool("HAKO_ANF_DEV")
}

/// Phase 145 P2: ANF strict mode (fail-fast on violations)
///
/// When enabled, ANF transformation errors result in immediate failure
/// instead of graceful fallback to legacy lowering.
///
/// # Environment Variable
///
/// `HAKO_ANF_STRICT=1` enables strict mode (default: OFF)
///
/// # Behavior
///
/// - **ON**: ANF violations return Err() with detailed error tags
/// - **OFF**: ANF violations gracefully fallback to legacy lowering (Ok(None))
///
/// # Use Cases
///
/// - **Development**: Catch order violations, pure-required violations early
/// - **Testing**: Verify ANF transformation correctness with fail-fast
/// - **Production**: Keep OFF for backward compatibility
///
/// # Example
///
/// ```bash
/// # Strict mode: Fail on `f() + g()` without ANF
/// HAKO_ANF_STRICT=1 ./hakorune program.hako
/// # Error: [joinir/anf/order_violation] f() + g(): both calls not hoisted
///
/// # Graceful mode (default): Fallback to legacy
/// ./hakorune program.hako
/// # OK: Legacy lowering used
/// ```
pub fn anf_strict_enabled() -> bool {
    env_bool("HAKO_ANF_STRICT")
}

/// Phase 146 P1: HAKO_ANF_ALLOW_PURE=1 - Allow ANF in PureOnly scope (dev-only)
///
/// Enables ANF transformation for PureOnly expression scopes (e.g., loop/if conditions).
/// Requires HAKO_ANF_DEV=1 to be set as well.
///
/// # Environment Variable
///
/// `HAKO_ANF_ALLOW_PURE=1` enables PureOnly ANF routing (default: OFF)
///
/// # Behavior
///
/// - **OFF (P0)**: ANF only for WithImpure scope (compound assignments)
/// - **ON (P1)**: ANF also for PureOnly scope (loop/if conditions with Compare)
///
/// # Use Cases
///
/// - **P1**: Enable `if (s.length() == 3)` ANF transformation
/// - **P147**: Enable `if (s1.length() < s2.length())` compound condition ANF
///
/// # Example
///
/// ```bash
/// # Enable condition ANF
/// HAKO_ANF_DEV=1 HAKO_ANF_ALLOW_PURE=1 ./hakorune program.hako
/// ```
pub fn anf_allow_pure_enabled() -> bool {
    env_bool("HAKO_ANF_ALLOW_PURE")
}
