//! Color theme. `NO_COLOR` (or empty terminal) disables every Style.

use ratatui::style::{Color, Style};

#[derive(Debug, Clone, Copy)]
pub struct Theme {
    pub colors_enabled: bool,
    pub border: Color,
    pub text: Color,
    pub group: Color,
}

impl Theme {
    pub fn from_env() -> Self {
        let no_color = std::env::var_os("NO_COLOR").is_some();
        Self::with_colors(!no_color)
    }

    pub fn with_colors(enabled: bool) -> Self {
        Self {
            colors_enabled: enabled,
            border: Color::Gray,
            text: Color::White,
            group: Color::DarkGray,
        }
    }

    pub fn style(&self, fg: Color) -> Style {
        if self.colors_enabled {
            Style::default().fg(fg)
        } else {
            Style::default()
        }
    }

    /// Map a JSON Canvas `color` field (`"1"`–`"6"` preset or `#hex`) to
    /// a [`Color`]. Unknown / invalid values fall back to `default`.
    pub fn map_color(&self, raw: Option<&str>, default: Color) -> Color {
        if !self.colors_enabled {
            return Color::Reset;
        }
        let Some(s) = raw else { return default };
        match s {
            "1" => Color::Red,
            "2" => Color::Rgb(255, 140, 0), // orange
            "3" => Color::Yellow,
            "4" => Color::Green,
            "5" => Color::Cyan,
            "6" => Color::Magenta,
            hex if hex.starts_with('#') => parse_hex(hex).unwrap_or(default),
            _ => default,
        }
    }
}

fn parse_hex(s: &str) -> Option<Color> {
    let s = s.strip_prefix('#')?;
    if s.len() != 6 {
        return None;
    }
    let r = u8::from_str_radix(&s[0..2], 16).ok()?;
    let g = u8::from_str_radix(&s[2..4], 16).ok()?;
    let b = u8::from_str_radix(&s[4..6], 16).ok()?;
    Some(Color::Rgb(r, g, b))
}

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

    #[test]
    fn no_color_returns_reset() {
        let t = Theme::with_colors(false);
        assert!(matches!(t.map_color(Some("1"), Color::White), Color::Reset));
    }

    #[test]
    fn presets_map() {
        let t = Theme::with_colors(true);
        assert!(matches!(t.map_color(Some("1"), Color::White), Color::Red));
        assert!(matches!(t.map_color(Some("4"), Color::White), Color::Green));
    }

    #[test]
    fn hex_map() {
        let t = Theme::with_colors(true);
        match t.map_color(Some("#ff0000"), Color::White) {
            Color::Rgb(255, 0, 0) => {}
            other => panic!("got {other:?}"),
        }
    }
}
