use std::str::FromStr;

use ratatui::style::Color;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ThemeVariant {
    Default,
    Framework,
    Alucard,
    CatppuccinFrappe,
    CatppuccinLatte,
    CatppuccinMacchiato,
    CatppuccinMocha,
    Dracula,
    GameBoy,
    GithubDark,
    GithubLight,
    GruvboxDark,
    GruvboxLight,
    MonochromeDark,
    MonochromeLight,
    MonokaiPro,
}

impl FromStr for ThemeVariant {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s.to_lowercase().as_str() {
            "default" => Ok(ThemeVariant::Default),
            "framework" => Ok(ThemeVariant::Framework),
            "alucard" => Ok(ThemeVariant::Alucard),
            "catppuccin_frappe" => Ok(ThemeVariant::CatppuccinFrappe),
            "catppuccin_latte" => Ok(ThemeVariant::CatppuccinLatte),
            "catppuccin_macchiato" => Ok(ThemeVariant::CatppuccinMacchiato),
            "catppuccin_mocha" => Ok(ThemeVariant::CatppuccinMocha),
            "dracula" => Ok(ThemeVariant::Dracula),
            "gameboy" => Ok(ThemeVariant::GameBoy),
            "github_dark" => Ok(ThemeVariant::GithubDark),
            "github_light" => Ok(ThemeVariant::GithubLight),
            "gruvbox_dark" => Ok(ThemeVariant::GruvboxDark),
            "gruvbox_light" => Ok(ThemeVariant::GruvboxLight),
            "monochrome_dark" => Ok(ThemeVariant::MonochromeDark),
            "monochrome_light" => Ok(ThemeVariant::MonochromeLight),
            "monokai_pro" => Ok(ThemeVariant::MonokaiPro),
            _ => Err(format!("Unknown theme: {}", s)),
        }
    }
}

impl ThemeVariant {
    pub fn name(&self) -> &'static str {
        match self {
            ThemeVariant::Default => "Default",
            ThemeVariant::Framework => "Framework",
            ThemeVariant::Alucard => "Alucard",
            ThemeVariant::CatppuccinFrappe => "Catppuccin Frappe",
            ThemeVariant::CatppuccinLatte => "Catppuccin Latte",
            ThemeVariant::CatppuccinMacchiato => "Catppuccin Macchiato",
            ThemeVariant::CatppuccinMocha => "Catppuccin Mocha",
            ThemeVariant::Dracula => "Dracula",
            ThemeVariant::GameBoy => "Game Boy",
            ThemeVariant::GithubDark => "GitHub Dark",
            ThemeVariant::GithubLight => "GitHub Light",
            ThemeVariant::GruvboxDark => "Gruvbox Dark",
            ThemeVariant::GruvboxLight => "Gruvbox Light",
            ThemeVariant::MonochromeDark => "Monochrome Dark",
            ThemeVariant::MonochromeLight => "Monochrome Light",
            ThemeVariant::MonokaiPro => "Monokai Pro",
        }
    }

    pub const ALL: [ThemeVariant; 16] = [
        ThemeVariant::Default,
        ThemeVariant::Framework,
        ThemeVariant::Alucard,
        ThemeVariant::CatppuccinFrappe,
        ThemeVariant::CatppuccinLatte,
        ThemeVariant::CatppuccinMacchiato,
        ThemeVariant::CatppuccinMocha,
        ThemeVariant::Dracula,
        ThemeVariant::GameBoy,
        ThemeVariant::GithubDark,
        ThemeVariant::GithubLight,
        ThemeVariant::GruvboxDark,
        ThemeVariant::GruvboxLight,
        ThemeVariant::MonochromeDark,
        ThemeVariant::MonochromeLight,
        ThemeVariant::MonokaiPro,
    ];

    pub fn next(&self) -> Self {
        let current_idx = Self::ALL.iter().position(|t| t == self).unwrap();
        Self::ALL[(current_idx + 1) % Self::ALL.len()]
    }

    pub fn previous(&self) -> Self {
        let current_idx = Self::ALL.iter().position(|t| t == self).unwrap();
        let prev_idx = if current_idx == 0 {
            Self::ALL.len() - 1
        } else {
            current_idx - 1
        };
        Self::ALL[prev_idx]
    }
}

pub struct Theme {
    pub variant: ThemeVariant,
    pub text: Color,
    pub background: Color,
    pub border: Color,
    pub border_active: Color,
    pub indication_ok: Color,
    pub indication_warning: Color,
    pub brightness_bar: Color,
    pub charge_bar: Color,
    pub bar_background: Color,
    pub highlighted_text: Color,
    pub informative_text: Color,
}

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

impl Theme {
    pub fn from_variant(variant: ThemeVariant) -> Self {
        match variant {
            ThemeVariant::Default => Self::default0(),
            ThemeVariant::Framework => Self::framework(),
            ThemeVariant::Alucard => Self::alucard(),
            ThemeVariant::CatppuccinFrappe => Self::catppuccin_frappe(),
            ThemeVariant::CatppuccinLatte => Self::catppuccin_latte(),
            ThemeVariant::CatppuccinMacchiato => Self::catppuccin_macchiato(),
            ThemeVariant::CatppuccinMocha => Self::catppuccin_mocha(),
            ThemeVariant::Dracula => Self::dracula(),
            ThemeVariant::GameBoy => Self::gameboy(),
            ThemeVariant::GithubDark => Self::github_dark(),
            ThemeVariant::GithubLight => Self::github_light(),
            ThemeVariant::GruvboxDark => Self::gruvbox_dark(),
            ThemeVariant::GruvboxLight => Self::gruvbox_light(),
            ThemeVariant::MonochromeDark => Self::monochrome_dark(),
            ThemeVariant::MonochromeLight => Self::monochrome_light(),
            ThemeVariant::MonokaiPro => Self::monokai_pro(),
        }
    }

    pub fn default0() -> Self {
        Self {
            variant: ThemeVariant::Default,
            text: Color::Indexed(7),
            background: Color::Indexed(0),
            border: Color::Indexed(15),
            border_active: Color::Indexed(3),
            indication_ok: Color::Indexed(2),
            indication_warning: Color::Indexed(1),
            brightness_bar: Color::Indexed(4),
            charge_bar: Color::Indexed(4),
            bar_background: Color::Indexed(0),
            highlighted_text: Color::Indexed(4),
            informative_text: Color::Indexed(5),
        }
    }

    pub fn framework() -> Self {
        Self {
            variant: ThemeVariant::Framework,
            text: Color::from_str("#F5F5F5").unwrap(),
            background: Color::from_str("#1F1F1F").unwrap(),
            border: Color::from_str("#F45A27").unwrap(),
            border_active: Color::from_str("#FFD600").unwrap(),
            indication_ok: Color::from_str("#00B16A").unwrap(),
            indication_warning: Color::from_str("#E53935").unwrap(),
            brightness_bar: Color::from_str("#fdbe54").unwrap(),
            charge_bar: Color::from_str("#9481D8").unwrap(),
            bar_background: Color::from_str("#363636").unwrap(),
            highlighted_text: Color::from_str("#AEC2C9").unwrap(),
            informative_text: Color::from_str("#9481D8").unwrap(),
        }
    }

    pub fn alucard() -> Self {
        Self {
            variant: ThemeVariant::Alucard,
            text: Color::from_str("#1F1F1F").unwrap(),
            background: Color::from_str("#FFFBEB").unwrap(),
            border: Color::from_str("#A34D14").unwrap(),
            border_active: Color::from_str("#846E15").unwrap(),
            indication_ok: Color::from_str("#14710A").unwrap(),
            indication_warning: Color::from_str("#CB3A2A").unwrap(),
            brightness_bar: Color::from_str("#846E15").unwrap(),
            charge_bar: Color::from_str("#644AC9").unwrap(),
            bar_background: Color::from_str("#CFCFDE").unwrap(),
            highlighted_text: Color::from_str("#036A96").unwrap(),
            informative_text: Color::from_str("#644AC9").unwrap(),
        }
    }

    pub fn catppuccin_frappe() -> Self {
        Self {
            variant: ThemeVariant::CatppuccinFrappe,
            text: Color::from_str("#C6D0F5").unwrap(),
            background: Color::from_str("#232634").unwrap(),
            border: Color::from_str("#EF9F76").unwrap(),
            border_active: Color::from_str("#E5C890").unwrap(),
            indication_ok: Color::from_str("#A6D189").unwrap(),
            indication_warning: Color::from_str("#E78284").unwrap(),
            brightness_bar: Color::from_str("#E5C890").unwrap(),
            charge_bar: Color::from_str("#8CAAEE").unwrap(),
            bar_background: Color::from_str("#303446").unwrap(),
            highlighted_text: Color::from_str("#8caaee").unwrap(),
            informative_text: Color::from_str("#CA9EE6").unwrap(),
        }
    }

    pub fn catppuccin_latte() -> Self {
        Self {
            variant: ThemeVariant::CatppuccinLatte,
            text: Color::from_str("#4C4F69").unwrap(),
            background: Color::from_str("#DCE0E8").unwrap(),
            border: Color::from_str("#D20F39").unwrap(),
            border_active: Color::from_str("#DF8E1D").unwrap(),
            indication_ok: Color::from_str("#40A02B").unwrap(),
            indication_warning: Color::from_str("#D20F39").unwrap(),
            brightness_bar: Color::from_str("#DF8E1D").unwrap(),
            charge_bar: Color::from_str("#1E66F5").unwrap(),
            bar_background: Color::from_str("#EFF1F5").unwrap(),
            highlighted_text: Color::from_str("#1e66f5").unwrap(),
            informative_text: Color::from_str("#8839EF").unwrap(),
        }
    }

    pub fn catppuccin_macchiato() -> Self {
        Self {
            variant: ThemeVariant::CatppuccinMacchiato,
            text: Color::from_str("#CAD3F5").unwrap(),
            background: Color::from_str("#181926").unwrap(),
            border: Color::from_str("#F5A97F").unwrap(),
            border_active: Color::from_str("#EED49F").unwrap(),
            indication_ok: Color::from_str("#A6DA95").unwrap(),
            indication_warning: Color::from_str("#ED8796").unwrap(),
            brightness_bar: Color::from_str("#EED49F").unwrap(),
            charge_bar: Color::from_str("#8AADF4").unwrap(),
            bar_background: Color::from_str("#24273A").unwrap(),
            highlighted_text: Color::from_str("#8aadf4").unwrap(),
            informative_text: Color::from_str("#C6A0F6").unwrap(),
        }
    }

    pub fn catppuccin_mocha() -> Self {
        Self {
            variant: ThemeVariant::CatppuccinMocha,
            text: Color::from_str("#CDD6F4").unwrap(),
            background: Color::from_str("#11111B").unwrap(),
            border: Color::from_str("#FAB387").unwrap(),
            border_active: Color::from_str("#F9E2AF").unwrap(),
            indication_ok: Color::from_str("#A6E3A1").unwrap(),
            indication_warning: Color::from_str("#F38BA8").unwrap(),
            brightness_bar: Color::from_str("#F9E2AF").unwrap(),
            charge_bar: Color::from_str("#89B4FA").unwrap(),
            bar_background: Color::from_str("#1E1E2E").unwrap(),
            highlighted_text: Color::from_str("#89b4fa").unwrap(),
            informative_text: Color::from_str("#CBA6f7").unwrap(),
        }
    }

    pub fn dracula() -> Self {
        Self {
            variant: ThemeVariant::Dracula,
            text: Color::from_str("#F8F8F2").unwrap(),
            background: Color::from_str("#282A36").unwrap(),
            border: Color::from_str("#FFB86C").unwrap(),
            border_active: Color::from_str("#FFB86C").unwrap(),
            indication_ok: Color::from_str("#50FA7B").unwrap(),
            indication_warning: Color::from_str("#FF5555").unwrap(),
            brightness_bar: Color::from_str("#F1FA8C").unwrap(),
            charge_bar: Color::from_str("#8BE9FD").unwrap(),
            bar_background: Color::from_str("#44475A").unwrap(),
            highlighted_text: Color::from_str("#8BE9FD").unwrap(),
            informative_text: Color::from_str("#BD93F9").unwrap(),
        }
    }

    pub fn gameboy() -> Self {
        Self {
            variant: ThemeVariant::GameBoy,
            text: Color::from_str("#9A9E3F").unwrap(),
            background: Color::from_str("#1B2A09").unwrap(),
            border: Color::from_str("#496B22").unwrap(),
            border_active: Color::from_str("#9A9E3F").unwrap(),
            indication_ok: Color::from_str("#9A9E3F").unwrap(),
            indication_warning: Color::from_str("#9A9E3F").unwrap(),
            brightness_bar: Color::from_str("#9A9E3F").unwrap(),
            charge_bar: Color::from_str("#9A9E3F").unwrap(),
            bar_background: Color::from_str("#0E450B").unwrap(),
            highlighted_text: Color::from_str("#9A9E3F").unwrap(),
            informative_text: Color::from_str("#9A9E3F").unwrap(),
        }
    }

    pub fn github_dark() -> Self {
        Self {
            variant: ThemeVariant::GithubDark,
            text: Color::from_str("#D1D7E0").unwrap(),
            background: Color::from_str("#212830").unwrap(),
            border: Color::from_str("#FF8E40").unwrap(),
            border_active: Color::from_str("#D3FA37").unwrap(),
            indication_ok: Color::from_str("#5fED83").unwrap(),
            indication_warning: Color::from_str("#FF8E40").unwrap(),
            brightness_bar: Color::from_str("#D3FA37").unwrap(),
            charge_bar: Color::from_str("#1F6FEB").unwrap(),
            bar_background: Color::from_str("#262C36").unwrap(),
            highlighted_text: Color::from_str("#9EECFF").unwrap(),
            informative_text: Color::from_str("#FF80D2").unwrap(),
        }
    }

    pub fn github_light() -> Self {
        Self {
            variant: ThemeVariant::GithubLight,
            text: Color::from_str("#000000").unwrap(),
            background: Color::from_str("#FFFFFF").unwrap(),
            border: Color::from_str("#703100").unwrap(),
            border_active: Color::from_str("#DB9D00").unwrap(),
            indication_ok: Color::from_str("#1f883D").unwrap(),
            indication_warning: Color::from_str("#703100").unwrap(),
            brightness_bar: Color::from_str("#DB9D00").unwrap(),
            charge_bar: Color::from_str("#0969DA").unwrap(),
            bar_background: Color::from_str("#F6F8FA").unwrap(),
            highlighted_text: Color::from_str("#212183").unwrap(),
            informative_text: Color::from_str("#8342FA").unwrap(),
        }
    }

    pub fn gruvbox_dark() -> Self {
        Self {
            variant: ThemeVariant::GruvboxDark,
            text: Color::from_str("#EBDBB2").unwrap(),
            background: Color::from_str("#282828").unwrap(),
            border: Color::from_str("#FE8019").unwrap(),
            border_active: Color::from_str("#FABd2F").unwrap(),
            indication_ok: Color::from_str("#B8BB26").unwrap(),
            indication_warning: Color::from_str("#FE8019").unwrap(),
            brightness_bar: Color::from_str("#FABD2F").unwrap(),
            charge_bar: Color::from_str("#458588").unwrap(),
            bar_background: Color::from_str("#504945").unwrap(),
            highlighted_text: Color::from_str("#83A598").unwrap(),
            informative_text: Color::from_str("#D3869B").unwrap(),
        }
    }

    pub fn gruvbox_light() -> Self {
        Self {
            variant: ThemeVariant::GruvboxLight,
            text: Color::from_str("#3C3836").unwrap(),
            background: Color::from_str("#FFFFFF").unwrap(),
            border: Color::from_str("#AF3A03").unwrap(),
            border_active: Color::from_str("#D79921").unwrap(),
            indication_ok: Color::from_str("#79740E").unwrap(),
            indication_warning: Color::from_str("#AF3A03").unwrap(),
            brightness_bar: Color::from_str("#B57614").unwrap(),
            charge_bar: Color::from_str("#458588").unwrap(),
            bar_background: Color::from_str("#D5C4A1").unwrap(),
            highlighted_text: Color::from_str("#076678").unwrap(),
            informative_text: Color::from_str("#8F3F71").unwrap(),
        }
    }

    pub fn monochrome_dark() -> Self {
        Self {
            variant: ThemeVariant::MonochromeDark,
            text: Color::from_str("#FFFFFF").unwrap(),
            background: Color::from_str("#000000").unwrap(),
            border: Color::from_str("#FFFFFF").unwrap(),
            border_active: Color::from_str("#FFFFFF").unwrap(),
            indication_ok: Color::from_str("#FFFFFF").unwrap(),
            indication_warning: Color::from_str("#FFFFFF").unwrap(),
            brightness_bar: Color::from_str("#FFFFFF").unwrap(),
            charge_bar: Color::from_str("#FFFFFF").unwrap(),
            bar_background: Color::from_str("#000000").unwrap(),
            highlighted_text: Color::from_str("#FFFFFF").unwrap(),
            informative_text: Color::from_str("#FFFFFF").unwrap(),
        }
    }

    pub fn monochrome_light() -> Self {
        Self {
            variant: ThemeVariant::MonochromeLight,
            text: Color::from_str("#000000").unwrap(),
            background: Color::from_str("#FFFFFF").unwrap(),
            border: Color::from_str("#000000").unwrap(),
            border_active: Color::from_str("#000000").unwrap(),
            indication_ok: Color::from_str("#000000").unwrap(),
            indication_warning: Color::from_str("#000000").unwrap(),
            brightness_bar: Color::from_str("#000000").unwrap(),
            charge_bar: Color::from_str("#000000").unwrap(),
            bar_background: Color::from_str("#FFFFFF").unwrap(),
            highlighted_text: Color::from_str("#000000").unwrap(),
            informative_text: Color::from_str("#000000").unwrap(),
        }
    }

    pub fn monokai_pro() -> Self {
        Self {
            variant: ThemeVariant::MonokaiPro,
            text: Color::from_str("#FFFFFF").unwrap(),
            background: Color::from_str("#161517").unwrap(),
            border: Color::from_str("#FC9867").unwrap(),
            border_active: Color::from_str("#FFD866").unwrap(),
            indication_ok: Color::from_str("#A9DC76").unwrap(),
            indication_warning: Color::from_str("#FF6188").unwrap(),
            brightness_bar: Color::from_str("#FFD866").unwrap(),
            charge_bar: Color::from_str("#AB9DF2").unwrap(),
            bar_background: Color::from_str("#373138").unwrap(),
            highlighted_text: Color::from_str("#77DCE8").unwrap(),
            informative_text: Color::from_str("#AB9DF2").unwrap(),
        }
    }
}
