//! Phase 171-C-5: TrimLoopHelper - Trim Pattern Lowering Helper
//!
//! This module provides a helper struct for Trim pattern lowering.
//! It encapsulates pattern-specific logic for converting LoopBodyLocal-based
//! conditions to carrier-based conditions.
//!
//! ## Purpose
//!
//! When a Trim pattern is detected (e.g., trim leading/trailing whitespace),
//! the LoopBodyCarrierPromoter promotes the LoopBodyLocal variable (like `ch`)
//! to a bool carrier (like `is_whitespace`).
//!
//! TrimLoopHelper stores the pattern information needed to:
//! 1. Generate carrier initialization code
//! 2. Generate carrier update code
//! 3. Map the promoted carrier back to the original variable semantics
//!
//! ## Example Use Case
//!
//! **Original pattern**:
//! ```nyash
//! loop(start < end) {
//!     local ch = s.substring(start, start+1)
//!     if ch == " " || ch == "\t" { start = start + 1 } else { break }
//! }
//! ```
//!
//! **After promotion**:
//! - Original variable: `ch`
//! - Promoted carrier: `is_whitespace` (bool)
//! - Comparison literals: `[" ", "\t"]`
//!
//! **TrimLoopHelper usage**:
//! ```rust
//! let helper = TrimLoopHelper {
//!     original_var: "ch".to_string(),
//!     carrier_name: "is_whitespace".to_string(),
//!     whitespace_chars: vec![" ".to_string(), "\t".to_string()],
//! };
//!
//! // Generate carrier initialization: is_whitespace = true
//! let init_value = helper.initial_value(); // true
//!
//! // Generate carrier update: is_whitespace = (ch == " " || ch == "\t")
//! let carrier_type = helper.carrier_type(); // "Bool"
//! ```

use super::loop_body_carrier_promoter::TrimPatternInfo;

/// Helper for Trim pattern lowering
///
/// Encapsulates the pattern-specific logic for converting
/// LoopBodyLocal-based conditions to carrier-based conditions.
///
/// # Fields
///
/// * `original_var` - The original LoopBodyLocal variable name (e.g., "ch")
/// * `carrier_name` - The promoted carrier name (e.g., "is_whitespace")
/// * `whitespace_chars` - The whitespace characters to compare against (e.g., [" ", "\t", "\n", "\r"])
///
/// # Design Philosophy
///
/// This struct follows Box Theory principles:
/// - **Single Responsibility**: Only handles Trim pattern lowering logic
/// - **Reusability**: Can be used by both Pattern2 and Pattern4 lowerers
/// - **Testability**: Pure data structure with simple accessors
#[derive(Debug, Clone)]
pub struct TrimLoopHelper {
    /// The original variable name (e.g., "ch")
    pub original_var: String,

    /// The promoted carrier name (e.g., "is_whitespace")
    pub carrier_name: String,

    /// Whitespace characters to compare against (e.g., [" ", "\t", "\n", "\r"])
    pub whitespace_chars: Vec<String>,
}

impl TrimLoopHelper {
    /// Create TrimLoopHelper from TrimPatternInfo
    ///
    /// # Arguments
    ///
    /// * `info` - The TrimPatternInfo from LoopBodyCarrierPromoter
    ///
    /// # Returns
    ///
    /// A new TrimLoopHelper with the same information
    ///
    /// # Example
    ///
    /// ```ignore
    /// let trim_info = TrimPatternInfo {
    ///     var_name: "ch".to_string(),
    ///     comparison_literals: vec![" ".to_string(), "\t".to_string()],
    ///     carrier_name: "is_whitespace".to_string(),
    /// };
    ///
    /// let helper = TrimLoopHelper::from_pattern_info(&trim_info);
    /// assert_eq!(helper.original_var, "ch");
    /// assert_eq!(helper.carrier_name, "is_whitespace");
    /// ```
    pub fn from_pattern_info(info: &TrimPatternInfo) -> Self {
        TrimLoopHelper {
            original_var: info.var_name.clone(),
            carrier_name: info.carrier_name.clone(),
            whitespace_chars: info.comparison_literals.clone(),
        }
    }

    /// Get the carrier type (always Bool for Trim pattern)
    ///
    /// Trim patterns always use bool carriers to represent
    /// "does the character match the whitespace set?"
    ///
    /// # Returns
    ///
    /// "Bool" - the carrier type name
    pub fn carrier_type(&self) -> &str {
        "Bool"
    }

    /// Get initial carrier value (true = continue looping)
    ///
    /// The carrier is initialized to `true` to represent
    /// "keep looping initially". When the character doesn't match
    /// whitespace, the carrier becomes `false` and the loop breaks.
    ///
    /// # Returns
    ///
    /// `true` - initial value for the carrier
    pub fn initial_value(&self) -> bool {
        true
    }

    /// Get the number of whitespace characters in the comparison set
    ///
    /// Useful for diagnostics and code generation.
    ///
    /// # Returns
    ///
    /// The count of whitespace characters (e.g., 4 for [" ", "\t", "\n", "\r"])
    pub fn whitespace_count(&self) -> usize {
        self.whitespace_chars.len()
    }

    /// Check if a specific character is in the whitespace set
    ///
    /// # Arguments
    ///
    /// * `ch` - The character to check (as a string slice)
    ///
    /// # Returns
    ///
    /// `true` if the character is in the whitespace set, `false` otherwise
    ///
    /// # Example
    ///
    /// ```ignore
    /// let helper = TrimLoopHelper {
    ///     whitespace_chars: vec![" ".to_string(), "\t".to_string()],
    ///     ..Default::default()
    /// };
    ///
    /// assert!(helper.is_whitespace(" "));
    /// assert!(helper.is_whitespace("\t"));
    /// assert!(!helper.is_whitespace("a"));
    /// ```
    pub fn is_whitespace(&self, ch: &str) -> bool {
        self.whitespace_chars.iter().any(|wc| wc == ch)
    }

    /// Check if this is a safe Trim pattern that can bypass LoopBodyLocal restrictions
    ///
    /// A safe Trim pattern must:
    /// 1. Have a valid carrier name
    /// 2. Have at least one whitespace character to compare
    /// 3. Have the expected structure (substring + OR chain + break)
    ///
    /// # Returns
    ///
    /// `true` if this is a safe Trim pattern, `false` otherwise
    ///
    /// # Example
    ///
    /// ```ignore
    /// let helper = TrimLoopHelper {
    ///     original_var: "ch".to_string(),
    ///     carrier_name: "is_whitespace".to_string(),
    ///     whitespace_chars: vec![" ".to_string(), "\t".to_string()],
    /// };
    /// assert!(helper.is_safe_trim());
    /// ```
    pub fn is_safe_trim(&self) -> bool {
        // Basic validation
        !self.carrier_name.is_empty() && !self.whitespace_chars.is_empty()
    }

    /// Alias for is_safe_trim() - checks if this follows the Trim-like pattern
    ///
    /// This method provides a semantic alias for safety checks.
    ///
    /// # Returns
    ///
    /// `true` if this pattern is Trim-like, `false` otherwise
    pub fn is_trim_like(&self) -> bool {
        self.is_safe_trim()
    }

    /// Check if this pattern has the expected Trim structure:
    /// - substring() method call
    /// - OR chain of equality comparisons
    /// - break on non-match
    ///
    /// # Returns
    ///
    /// `true` if the pattern has valid structure, `false` otherwise
    ///
    /// # Implementation Note
    ///
    /// For now, just check basic requirements.
    /// The full structure was already validated by LoopBodyCarrierPromoter.
    pub fn has_valid_structure(&self) -> bool {
        !self.original_var.is_empty()
            && !self.carrier_name.is_empty()
            && !self.whitespace_chars.is_empty()
    }
}

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

    #[test]
    fn test_from_pattern_info() {
        let trim_info = TrimPatternInfo {
            var_name: "ch".to_string(),
            comparison_literals: vec![" ".to_string(), "\t".to_string()],
            carrier_name: "is_ch_match".to_string(),
        };

        let helper = TrimLoopHelper::from_pattern_info(&trim_info);

        assert_eq!(helper.original_var, "ch");
        assert_eq!(helper.carrier_name, "is_ch_match");
        assert_eq!(helper.whitespace_chars.len(), 2);
        assert!(helper.whitespace_chars.contains(&" ".to_string()));
        assert!(helper.whitespace_chars.contains(&"\t".to_string()));
    }

    #[test]
    fn test_carrier_type() {
        let helper = TrimLoopHelper {
            original_var: "ch".to_string(),
            carrier_name: "is_whitespace".to_string(),
            whitespace_chars: vec![],
        };

        assert_eq!(helper.carrier_type(), "Bool");
    }

    #[test]
    fn test_initial_value() {
        let helper = TrimLoopHelper {
            original_var: "ch".to_string(),
            carrier_name: "is_whitespace".to_string(),
            whitespace_chars: vec![],
        };

        assert_eq!(helper.initial_value(), true);
    }

    #[test]
    fn test_whitespace_count() {
        let helper = TrimLoopHelper {
            original_var: "ch".to_string(),
            carrier_name: "is_whitespace".to_string(),
            whitespace_chars: vec![
                " ".to_string(),
                "\t".to_string(),
                "\n".to_string(),
                "\r".to_string(),
            ],
        };

        assert_eq!(helper.whitespace_count(), 4);
    }

    #[test]
    fn test_is_whitespace() {
        let helper = TrimLoopHelper {
            original_var: "ch".to_string(),
            carrier_name: "is_whitespace".to_string(),
            whitespace_chars: vec![" ".to_string(), "\t".to_string()],
        };

        assert!(helper.is_whitespace(" "));
        assert!(helper.is_whitespace("\t"));
        assert!(!helper.is_whitespace("\n"));
        assert!(!helper.is_whitespace("a"));
    }

    #[test]
    fn test_is_safe_trim() {
        let helper = TrimLoopHelper {
            original_var: "ch".to_string(),
            carrier_name: "is_whitespace".to_string(),
            whitespace_chars: vec![" ".to_string(), "\t".to_string()],
        };
        assert!(helper.is_safe_trim());
        assert!(helper.is_trim_like());
    }

    #[test]
    fn test_is_safe_trim_empty_carrier() {
        let helper = TrimLoopHelper {
            original_var: "ch".to_string(),
            carrier_name: "".to_string(), // Empty!
            whitespace_chars: vec![" ".to_string()],
        };
        assert!(!helper.is_safe_trim());
    }

    #[test]
    fn test_is_safe_trim_no_whitespace() {
        let helper = TrimLoopHelper {
            original_var: "ch".to_string(),
            carrier_name: "is_whitespace".to_string(),
            whitespace_chars: vec![], // Empty!
        };
        assert!(!helper.is_safe_trim());
    }

    #[test]
    fn test_has_valid_structure() {
        let helper = TrimLoopHelper {
            original_var: "ch".to_string(),
            carrier_name: "is_whitespace".to_string(),
            whitespace_chars: vec![" ".to_string()],
        };
        assert!(helper.has_valid_structure());
    }
}
