//! # Utility Functions and Helpers

/// Terminal size utilities
pub mod terminal {
    /// Check if terminal is large enough for comfortable operation
    #[must_use]
    pub const fn is_terminal_large_enough(width: u16, height: u16) -> bool {
        width >= 40 && height >= 10
    }

    /// Get recommended minimum terminal size
    #[must_use]
    pub const fn min_recommended_size() -> (u16, u16) {
        (80, 24) // Standard terminal size
    }

    /// Check if terminal meets recommended size
    #[must_use]
    pub const fn is_terminal_recommended_size(width: u16, height: u16) -> bool {
        width >= 80 && height >= 24
    }
}

/// String utilities for text handling
pub mod text {
    /// Truncate string to max length with ellipsis
    #[must_use]
    pub fn truncate_with_ellipsis(text: &str, max_len: usize) -> String {
        if text.len() <= max_len {
            text.to_string()
        } else if max_len > 3 {
            format!("{}…", &text[..max_len - 1])
        } else {
            "…".to_string()
        }
    }

    /// Center text within a width (pads both sides)
    #[must_use]
    pub fn center_text(text: &str, width: usize) -> String {
        let text_len = text.len();
        if text_len >= width {
            text.to_string()
        } else {
            let total_pad = width - text_len;
            let left_pad = total_pad / 2;
            let right_pad = total_pad - left_pad;
            format!(
                "{:left$}{}{:right$}",
                "",
                text,
                "",
                left = left_pad,
                right = right_pad
            )
        }
    }

    /// Pad text to width
    #[must_use]
    pub fn pad_text(text: &str, width: usize) -> String {
        format!("{text:<width$}")
    }

    /// Replace multiple spaces with single space
    #[must_use]
    pub fn normalize_spaces(text: &str) -> String {
        text.split_whitespace().collect::<Vec<_>>().join(" ")
    }

    /// Wrap text to specified width
    #[must_use]
    pub fn wrap_text(text: &str, width: usize) -> Vec<String> {
        let mut lines = Vec::new();
        let mut current_line = String::new();

        for word in text.split_whitespace() {
            if current_line.is_empty() {
                current_line = word.to_string();
            } else if current_line.len() + word.len() < width {
                current_line.push(' ');
                current_line.push_str(word);
            } else {
                lines.push(current_line.clone());
                current_line = word.to_string();
            }
        }

        if !current_line.is_empty() {
            lines.push(current_line);
        }

        lines
    }
}

/// List utilities
pub mod list {
    /// Calculate safe index after navigation
    #[must_use]
    pub const fn navigate_down(current: usize, len: usize) -> usize {
        if len == 0 {
            0
        } else {
            (current + 1) % len
        }
    }

    /// Calculate safe index when navigating up
    #[must_use]
    pub const fn navigate_up(current: usize, len: usize) -> usize {
        if len == 0 {
            0
        } else if current == 0 {
            len - 1
        } else {
            current - 1
        }
    }

    /// Clamp index to valid range
    #[must_use]
    pub fn clamp_index(index: usize, len: usize) -> usize {
        if len == 0 {
            0
        } else {
            index.min(len - 1)
        }
    }
}

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

    #[test]
    fn test_terminal_large_enough() {
        assert!(terminal::is_terminal_large_enough(80, 24));
        assert!(!terminal::is_terminal_large_enough(20, 5));
    }

    #[test]
    fn test_terminal_recommended_size() {
        assert!(terminal::is_terminal_recommended_size(80, 24));
        assert!(!terminal::is_terminal_recommended_size(40, 24));
    }

    #[test]
    fn test_truncate_with_ellipsis() {
        assert_eq!(text::truncate_with_ellipsis("hello", 4), "hel…"); // Takes first 3 chars + ellipsis
        assert_eq!(text::truncate_with_ellipsis("hello", 3), "…"); // max_len == 3
        assert_eq!(text::truncate_with_ellipsis("hi", 5), "hi"); // Short string unchanged
    }

    #[test]
    fn test_center_text() {
        let centered = text::center_text("test", 10);
        assert_eq!(centered.len(), 10);
        assert!(centered.contains("test"));
    }

    #[test]
    fn test_normalize_spaces() {
        assert_eq!(text::normalize_spaces("hello   world"), "hello world");
        assert_eq!(text::normalize_spaces("  test  "), "test");
    }

    #[test]
    fn test_wrap_text() {
        let wrapped = text::wrap_text("hello world test", 10);
        assert!(wrapped.len() > 1);
        assert_eq!(wrapped[0], "hello");
    }

    #[test]
    fn test_navigate_down() {
        assert_eq!(list::navigate_down(0, 5), 1);
        assert_eq!(list::navigate_down(4, 5), 0); // wraps
        assert_eq!(list::navigate_down(0, 0), 0); // empty
    }

    #[test]
    fn test_navigate_up() {
        assert_eq!(list::navigate_up(1, 5), 0);
        assert_eq!(list::navigate_up(0, 5), 4); // wraps
        assert_eq!(list::navigate_up(0, 0), 0); // empty
    }

    #[test]
    fn test_clamp_index() {
        assert_eq!(list::clamp_index(2, 5), 2);
        assert_eq!(list::clamp_index(10, 5), 4);
        assert_eq!(list::clamp_index(0, 0), 0);
    }
}
