//! Configuration and theming system
//!
//! Implements R-CONSISTENT-THEMING: Define a theme structure for consistent styling
//! across the application. All colors and styles are defined in one place.

use ratatui::style::{Color, Modifier, Style};
use serde::{Deserialize, Serialize};
use std::fmt;

/// Theme colors and styling
///
/// Implements semantic colors for consistent UX:
/// - Primary: Main color for headers and emphasis
/// - Success: Green for success messages
/// - Warning: Yellow for warnings
/// - Error: Red for errors
/// - Bg/Fg: Background and foreground colors
#[derive(Clone, Copy, Debug)]
pub struct Theme {
    /// Primary color for headers and selected items
    pub primary: Color,
    /// Color for success messages
    pub success: Color,
    /// Color for warning messages
    pub warning: Color,
    /// Color for error messages
    pub error: Color,
    /// Secondary color for less important elements
    pub secondary: Color,
    /// Background color
    pub bg: Color,
    /// Foreground/text color
    pub fg: Color,
}

impl Theme {
    /// Create a dark theme (default)
    #[must_use]
    pub const fn dark() -> Self {
        Self {
            primary: Color::Cyan,
            success: Color::Green,
            warning: Color::Yellow,
            error: Color::Red,
            secondary: Color::Gray,
            bg: Color::Black,
            fg: Color::White,
        }
    }

    /// Create a light theme
    #[must_use]
    pub const fn light() -> Self {
        Self {
            primary: Color::Blue,
            success: Color::Green,
            warning: Color::Magenta,
            error: Color::Red,
            secondary: Color::DarkGray,
            bg: Color::White,
            fg: Color::Black,
        }
    }

    /// Create a minimal theme (high contrast)
    #[must_use]
    pub const fn minimal() -> Self {
        Self {
            primary: Color::White,
            success: Color::Green,
            warning: Color::Yellow,
            error: Color::Red,
            secondary: Color::Gray,
            bg: Color::Black,
            fg: Color::White,
        }
    }

    /// Create a professional theme (blue)
    #[must_use]
    pub const fn professional() -> Self {
        Self {
            primary: Color::Blue,
            success: Color::Green,
            warning: Color::Yellow,
            error: Color::Red,
            secondary: Color::Cyan,
            bg: Color::Black,
            fg: Color::White,
        }
    }

    /// Style for headers
    #[must_use]
    pub fn header_style(&self) -> Style {
        Style::default()
            .fg(self.primary)
            .add_modifier(Modifier::BOLD)
    }

    /// Style for selected items
    #[must_use]
    pub fn selected_style(&self) -> Style {
        Style::default()
            .fg(self.bg)
            .bg(self.primary)
            .add_modifier(Modifier::BOLD)
    }

    /// Style for success messages
    #[must_use]
    pub fn success_style(&self) -> Style {
        Style::default()
            .fg(self.success)
            .add_modifier(Modifier::BOLD)
    }

    /// Style for warning messages
    #[must_use]
    pub fn warning_style(&self) -> Style {
        Style::default()
            .fg(self.warning)
            .add_modifier(Modifier::BOLD)
    }

    /// Style for error messages
    #[must_use]
    pub fn error_style(&self) -> Style {
        Style::default().fg(self.error).add_modifier(Modifier::BOLD)
    }

    /// Style for normal text
    #[must_use]
    pub fn normal_style(&self) -> Style {
        Style::default().fg(self.fg)
    }

    /// Style for dimmed/secondary text
    #[must_use]
    pub fn dimmed_style(&self) -> Style {
        Style::default()
            .fg(self.secondary)
            .add_modifier(Modifier::DIM)
    }

    /// Style for focused elements
    #[must_use]
    pub fn focused_style(&self) -> Style {
        Style::default()
            .fg(self.primary)
            .add_modifier(Modifier::BOLD | Modifier::UNDERLINED)
    }

    /// Get success color
    #[must_use]
    pub const fn success_color(&self) -> Color {
        self.success
    }

    /// Get warning color
    #[must_use]
    pub const fn warning_color(&self) -> Color {
        self.warning
    }

    /// Get error color
    #[must_use]
    pub const fn error_color(&self) -> Color {
        self.error
    }

    /// Get text color
    #[must_use]
    pub const fn text_color(&self) -> Color {
        self.fg
    }

    /// Get muted text color
    #[must_use]
    pub const fn text_muted_color(&self) -> Color {
        self.secondary
    }

    /// Get title color
    #[must_use]
    pub const fn title_color(&self) -> Color {
        self.primary
    }

    /// Get border color
    #[must_use]
    pub const fn border_color(&self) -> Color {
        self.secondary
    }

    /// Get selection color
    #[must_use]
    pub const fn selection_color(&self) -> Color {
        self.primary
    }

    /// Check if theme is dark
    #[must_use]
    pub fn is_dark(&self) -> bool {
        self.bg == Color::Black
    }

    /// Get background color
    #[must_use]
    pub const fn background(&self) -> Color {
        self.bg
    }
}

impl Default for Theme {
    fn default() -> Self {
        Self::dark()
    }
}

/// Configurable key bindings
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct KeyBindings {
    /// Keys to quit application
    pub quit: Vec<String>,
    /// Keys to move up
    pub up: Vec<String>,
    /// Keys to move down
    pub down: Vec<String>,
    /// Keys to move left
    pub left: Vec<String>,
    /// Keys to move right
    pub right: Vec<String>,
    /// Keys to confirm/select
    pub confirm: Vec<String>,
    /// Keys to cancel
    pub cancel: Vec<String>,
    /// Keys for help
    pub help: Vec<String>,
}

impl KeyBindings {
    /// Create default Vim-style key bindings
    #[must_use]
    pub fn vim_style() -> Self {
        Self {
            quit: vec!["q".to_string(), "Esc".to_string()],
            up: vec!["k".to_string(), "Up".to_string()],
            down: vec!["j".to_string(), "Down".to_string()],
            left: vec!["h".to_string(), "Left".to_string()],
            right: vec!["l".to_string(), "Right".to_string()],
            confirm: vec!["Enter".to_string()],
            cancel: vec!["Esc".to_string()],
            help: vec!["?".to_string()],
        }
    }
}

impl Default for KeyBindings {
    fn default() -> Self {
        Self::vim_style()
    }
}

/// TUI configuration
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TuiConfig {
    /// Selected theme
    pub theme: String,
    /// Event polling timeout in milliseconds
    pub tick_rate_ms: u64,
    /// Enable mouse support
    pub enable_mouse: bool,
    /// Key bindings
    pub keybindings: KeyBindings,
}

impl TuiConfig {
    /// Load from TOML configuration file
    ///
    /// # Errors
    /// Returns an error if the TOML content is invalid or cannot be parsed.
    pub fn from_toml(content: &str) -> anyhow::Result<Self> {
        Ok(toml::from_str(content)?)
    }
}

impl Default for TuiConfig {
    fn default() -> Self {
        Self {
            theme: "dark".to_string(),
            tick_rate_ms: 250,
            enable_mouse: true,
            keybindings: KeyBindings::default(),
        }
    }
}

/// Status indicator styling
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Status {
    /// Normal status
    Normal,
    /// Active/selected status
    Active,
    /// Success status
    Success,
    /// Warning status
    Warning,
    /// Error status
    Error,
}

impl Status {
    /// Get color for this status
    #[must_use]
    pub const fn color(&self) -> Color {
        match self {
            Self::Normal => Color::White,
            Self::Active => Color::Cyan,
            Self::Success => Color::Green,
            Self::Warning => Color::Yellow,
            Self::Error => Color::Red,
        }
    }

    /// Get style for this status
    #[must_use]
    pub fn style(&self) -> Style {
        Style::default().fg(self.color())
    }
}

impl fmt::Display for Status {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Normal => write!(f, "normal"),
            Self::Active => write!(f, "active"),
            Self::Success => write!(f, "success"),
            Self::Warning => write!(f, "warning"),
            Self::Error => write!(f, "error"),
        }
    }
}

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

    #[test]
    fn test_theme_dark() {
        let theme = Theme::dark();
        assert_eq!(theme.primary, Color::Cyan);
        assert_eq!(theme.success, Color::Green);
    }

    #[test]
    fn test_theme_light() {
        let theme = Theme::light();
        assert_eq!(theme.primary, Color::Blue);
        assert_eq!(theme.bg, Color::White);
    }

    #[test]
    fn test_theme_header_style() {
        let theme = Theme::dark();
        let style = theme.header_style();
        assert_eq!(style.fg, Some(Color::Cyan));
    }

    #[test]
    fn test_keybindings_default() {
        let bindings = KeyBindings::default();
        assert!(bindings.quit.contains(&"q".to_string()));
        assert!(bindings.up.contains(&"k".to_string()));
    }

    #[test]
    fn test_tui_config_default() {
        let config = TuiConfig::default();
        assert_eq!(config.theme, "dark");
        assert_eq!(config.tick_rate_ms, 250);
        assert!(config.enable_mouse);
    }

    #[test]
    fn test_status_color() {
        assert_eq!(Status::Success.color(), Color::Green);
        assert_eq!(Status::Error.color(), Color::Red);
    }

    #[test]
    fn test_status_display() {
        assert_eq!(Status::Normal.to_string(), "normal");
        assert_eq!(Status::Error.to_string(), "error");
    }

    #[test]
    fn test_theme_selected_style() {
        let theme = Theme::dark();
        let style = theme.selected_style();
        assert_eq!(style.fg, Some(Color::Black));
        assert_eq!(style.bg, Some(Color::Cyan));
    }
}
