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

use crate::app::model::shared::theme_id::ThemeId;
use crate::app::policy::write::write_guardrails::RiskLevel;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StatusTone {
    Success,
    Error,
    Warning,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ThemePalette {
    pub semantic: SemanticTokens,
    pub component: ComponentTokens,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SemanticTokens {
    pub surface: SurfaceTokens,
    pub text: TextTokens,
    pub status: StatusTokens,
    pub cursor: CursorTokens,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SurfaceTokens {
    pub focus_border: Color,
    pub unfocus_border: Color,
    pub highlight_border: Color,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TextTokens {
    pub primary: Color,
    pub secondary: Color,
    pub muted: Color,
    pub dim: Color,
    pub accent: Color,
    pub placeholder: Color,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct StatusTokens {
    pub success: Color,
    pub error: Color,
    pub warning: Color,
    pub pending: Color,
    pub medium_risk: Color,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct CursorTokens {
    pub fg: Color,
    pub bg: Color,
    pub text_fg: Color,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ComponentTokens {
    pub modal: ModalTokens,
    pub navigation: NavigationTokens,
    pub editor: EditorTokens,
    pub table: TableTokens,
    pub feedback: FeedbackTokens,
    pub syntax: SyntaxTokens,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ModalTokens {
    pub title: Color,
    pub hint: Color,
    pub border: Color,
    pub border_highlight: Color,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct NavigationTokens {
    pub key_chip_bg: Color,
    pub key_chip_fg: Color,
    pub section_header: Color,
    pub scrollbar_active: Color,
    pub scrollbar_inactive: Color,
    pub tab_active: Color,
    pub tab_inactive: Color,
    pub active_indicator: Color,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct EditorTokens {
    pub current_line_bg: Color,
    pub completion_selected_bg: Color,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TableTokens {
    pub result_row_active_bg: Color,
    pub result_cell_active_bg: Color,
    pub cell_edit_fg: Color,
    pub staged_delete_bg: Color,
    pub staged_delete_fg: Color,
    pub striped_row_bg: Color,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct FeedbackTokens {
    pub yank_flash_bg: Color,
    pub yank_flash_fg: Color,
    pub note_text: Color,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SyntaxTokens {
    pub sql_keyword: Color,
    pub sql_string: Color,
    pub sql_number: Color,
    pub sql_comment: Color,
    pub sql_operator: Color,
    pub sql_text: Color,
}

impl ThemePalette {
    pub fn risk_color(&self, level: RiskLevel) -> Color {
        match level {
            RiskLevel::Low => self.semantic.status.warning,
            RiskLevel::Medium => self.semantic.status.medium_risk,
            RiskLevel::High => self.semantic.status.error,
        }
    }

    pub fn modal_title_style(&self) -> Style {
        Style::default()
            .fg(self.component.modal.title)
            .add_modifier(Modifier::BOLD)
    }

    pub fn modal_hint_style(&self) -> Style {
        Style::default().fg(self.component.modal.hint)
    }

    pub fn panel_border_style(&self, focused: bool, highlight: bool) -> Style {
        let color = if focused {
            self.semantic.surface.focus_border
        } else if highlight {
            self.semantic.surface.highlight_border
        } else {
            self.semantic.surface.unfocus_border
        };
        Style::default().fg(color)
    }

    pub fn picker_selected_style(&self) -> Style {
        Style::default()
            .bg(self.component.editor.completion_selected_bg)
            .fg(self.semantic.text.primary)
            .add_modifier(Modifier::BOLD)
    }

    pub fn modal_input_border_style(&self, focused: bool, has_error: bool) -> Style {
        let color = if has_error {
            self.semantic.status.error
        } else if focused {
            self.component.modal.border_highlight
        } else {
            self.component.modal.border
        };
        Style::default().fg(color)
    }

    pub fn modal_border_style(&self) -> Style {
        Style::default().fg(self.component.modal.border)
    }

    pub fn status_style(&self, tone: StatusTone) -> Style {
        let color = match tone {
            StatusTone::Success => self.semantic.status.success,
            StatusTone::Error => self.semantic.status.error,
            StatusTone::Warning => self.semantic.status.warning,
        };
        Style::default().fg(color)
    }

    pub fn block_cursor_style(&self) -> Style {
        Style::default()
            .bg(self.semantic.cursor.bg)
            .fg(self.semantic.cursor.text_fg)
    }

    pub fn insert_cursor_style(&self) -> Style {
        Style::default().fg(self.semantic.cursor.fg)
    }
}

pub const DEFAULT_THEME: ThemePalette = ThemePalette {
    semantic: SemanticTokens {
        surface: SurfaceTokens {
            focus_border: Color::Rgb(0x97, 0xc9, 0xc3),
            unfocus_border: Color::Rgb(0x45, 0x47, 0x55),
            highlight_border: Color::Rgb(0xb0, 0xdd, 0xd8),
        },
        text: TextTokens {
            primary: Color::Rgb(0xe9, 0xdb, 0xdb),
            secondary: Color::Rgb(0xc0, 0xb8, 0xb8),
            muted: Color::Rgb(0x5c, 0x63, 0x70),
            dim: Color::Rgb(0x6a, 0x6e, 0x7a),
            accent: Color::Rgb(0xd4, 0xa4, 0x85),
            placeholder: Color::Rgb(0x5b, 0x5f, 0x6e),
        },
        status: StatusTokens {
            success: Color::Rgb(0x97, 0xc9, 0xc3),
            error: Color::Rgb(0xc4, 0x74, 0x6e),
            warning: Color::Rgb(0xe0, 0xaf, 0x68),
            pending: Color::Rgb(0xd4, 0xa0, 0x60),
            medium_risk: Color::Rgb(0xd4, 0x70, 0x50),
        },
        cursor: CursorTokens {
            fg: Color::White,
            bg: Color::White,
            text_fg: Color::Black,
        },
    },
    component: ComponentTokens {
        modal: ModalTokens {
            title: Color::Rgb(0xe9, 0xdb, 0xdb),
            hint: Color::Rgb(0xc0, 0xb8, 0xb0),
            border: Color::Rgb(0x76, 0x7a, 0x84),
            border_highlight: Color::Rgb(0xc0, 0xb8, 0xb8),
        },
        navigation: NavigationTokens {
            key_chip_bg: Color::Rgb(0x3a, 0x3a, 0x4a),
            key_chip_fg: Color::Rgb(0xd4, 0xa4, 0x85),
            section_header: Color::Rgb(0x6a, 0xb8, 0x9a),
            scrollbar_active: Color::Rgb(0xc0, 0xb8, 0xb0),
            scrollbar_inactive: Color::Rgb(0x50, 0x52, 0x5e),
            tab_active: Color::Rgb(0xd0, 0xc0, 0xa0),
            tab_inactive: Color::Rgb(0x5b, 0x5f, 0x6e),
            active_indicator: Color::Rgb(0xff, 0xff, 0xff),
        },
        editor: EditorTokens {
            current_line_bg: Color::Rgb(0x22, 0x26, 0x33),
            completion_selected_bg: Color::Rgb(0x45, 0x47, 0x5a),
        },
        table: TableTokens {
            result_row_active_bg: Color::Rgb(0x2e, 0x2e, 0x44),
            result_cell_active_bg: Color::Rgb(0x3a, 0x3a, 0x5a),
            cell_edit_fg: Color::Rgb(0xa8, 0xb8, 0xb5),
            staged_delete_bg: Color::Rgb(0x3d, 0x22, 0x22),
            staged_delete_fg: Color::Rgb(0xee, 0x77, 0x77),
            striped_row_bg: Color::Rgb(0x1e, 0x1e, 0x23),
        },
        feedback: FeedbackTokens {
            yank_flash_bg: Color::Rgb(0xF4, 0x9E, 0x4C),
            yank_flash_fg: Color::Rgb(0x11, 0x14, 0x19),
            note_text: Color::Rgb(0x66, 0x66, 0x77),
        },
        syntax: SyntaxTokens {
            sql_keyword: Color::Rgb(0x80, 0x90, 0xa8),
            sql_string: Color::Rgb(0xcd, 0xc8, 0xdb),
            sql_number: Color::Rgb(0xd4, 0xa4, 0x85),
            sql_comment: Color::Rgb(0x62, 0x72, 0xa4),
            sql_operator: Color::Rgb(0x8a, 0x91, 0xa5),
            sql_text: Color::Rgb(0xe9, 0xdb, 0xdb),
        },
    },
};

pub const LIGHT_THEME: ThemePalette = ThemePalette {
    semantic: SemanticTokens {
        surface: SurfaceTokens {
            focus_border: Color::Rgb(0x0f, 0x7f, 0x72),
            unfocus_border: Color::Rgb(0x98, 0x92, 0x98),
            highlight_border: Color::Rgb(0x00, 0x8f, 0x80),
        },
        text: TextTokens {
            primary: Color::Rgb(0x2c, 0x28, 0x2d),
            secondary: Color::Rgb(0x5f, 0x58, 0x5d),
            muted: Color::Rgb(0x64, 0x5f, 0x68),
            dim: Color::Rgb(0x72, 0x6c, 0x76),
            accent: Color::Rgb(0x85, 0x4f, 0x31),
            placeholder: Color::Rgb(0x72, 0x6c, 0x76),
        },
        status: StatusTokens {
            success: Color::Rgb(0x2f, 0x7f, 0x68),
            error: Color::Rgb(0xb3, 0x26, 0x1e),
            warning: Color::Rgb(0x9b, 0x68, 0x1f),
            pending: Color::Rgb(0x9a, 0x63, 0x23),
            medium_risk: Color::Rgb(0xb4, 0x54, 0x32),
        },
        cursor: CursorTokens {
            fg: Color::Rgb(0x0f, 0x7f, 0x72),
            bg: Color::Rgb(0x0f, 0x7f, 0x72),
            text_fg: Color::Rgb(0xff, 0xff, 0xff),
        },
    },
    component: ComponentTokens {
        modal: ModalTokens {
            title: Color::Rgb(0x2c, 0x28, 0x2d),
            hint: Color::Rgb(0x65, 0x5d, 0x61),
            border: Color::Rgb(0x96, 0x98, 0xa0),
            border_highlight: Color::Rgb(0x3f, 0x70, 0x6a),
        },
        navigation: NavigationTokens {
            key_chip_bg: Color::Rgb(0xe8, 0xe3, 0xe6),
            key_chip_fg: Color::Rgb(0x85, 0x4f, 0x31),
            section_header: Color::Rgb(0x3f, 0x7e, 0x67),
            scrollbar_active: Color::Rgb(0x6f, 0x8f, 0x8a),
            scrollbar_inactive: Color::Rgb(0xc8, 0xc2, 0xc7),
            tab_active: Color::Rgb(0x7c, 0x63, 0x2d),
            tab_inactive: Color::Rgb(0x64, 0x5f, 0x68),
            active_indicator: Color::Rgb(0x0f, 0x7f, 0x72),
        },
        editor: EditorTokens {
            current_line_bg: Color::Rgb(0xe9, 0xf0, 0xef),
            completion_selected_bg: Color::Rgb(0xd4, 0xe5, 0xe2),
        },
        table: TableTokens {
            result_row_active_bg: Color::Rgb(0xe3, 0xed, 0xeb),
            result_cell_active_bg: Color::Rgb(0xd0, 0xe2, 0xdf),
            cell_edit_fg: Color::Rgb(0x4a, 0x78, 0x72),
            staged_delete_bg: Color::Rgb(0xf3, 0xdd, 0xdb),
            staged_delete_fg: Color::Rgb(0xb3, 0x26, 0x1e),
            striped_row_bg: Color::Rgb(0xf1, 0xf5, 0xf4),
        },
        feedback: FeedbackTokens {
            yank_flash_bg: Color::Rgb(0xf1, 0xc7, 0x79),
            yank_flash_fg: Color::Rgb(0x2c, 0x28, 0x2d),
            note_text: Color::Rgb(0x72, 0x6c, 0x76),
        },
        syntax: SyntaxTokens {
            sql_keyword: Color::Rgb(0x3f, 0x5f, 0x8d),
            sql_string: Color::Rgb(0x55, 0x76, 0x64),
            sql_number: Color::Rgb(0x8f, 0x56, 0x36),
            sql_comment: Color::Rgb(0x7a, 0x74, 0x8c),
            sql_operator: Color::Rgb(0x6d, 0x72, 0x88),
            sql_text: Color::Rgb(0x2c, 0x28, 0x2d),
        },
    },
};

#[cfg(any(test, feature = "test-support"))]
#[doc(hidden)]
pub const TEST_CONTRAST_THEME: ThemePalette = ThemePalette {
    semantic: SemanticTokens {
        surface: SurfaceTokens {
            focus_border: Color::Rgb(0x2f, 0xc4, 0xb2),
            unfocus_border: Color::Rgb(0x5d, 0x62, 0x74),
            highlight_border: Color::Rgb(0xff, 0xc8, 0x57),
        },
        text: TextTokens {
            primary: Color::Rgb(0xf6, 0xf0, 0xe8),
            secondary: Color::Rgb(0xc9, 0xd6, 0xdf),
            muted: Color::Rgb(0x92, 0xb3, 0xc2),
            dim: Color::Rgb(0x6a, 0x85, 0x95),
            accent: Color::Rgb(0xff, 0xc8, 0x57),
            placeholder: Color::Rgb(0x92, 0xb3, 0xc2),
        },
        status: StatusTokens {
            success: Color::Rgb(0x7b, 0xe0, 0x73),
            error: Color::Rgb(0xff, 0x7a, 0x59),
            warning: Color::Rgb(0xff, 0xc8, 0x57),
            pending: Color::Rgb(0xff, 0x9f, 0x1c),
            medium_risk: Color::Rgb(0xff, 0x9f, 0x1c),
        },
        cursor: CursorTokens {
            fg: Color::Rgb(0xff, 0xf4, 0xe0),
            bg: Color::Rgb(0xff, 0xf4, 0xe0),
            text_fg: Color::Rgb(0x0d, 0x11, 0x18),
        },
    },
    component: ComponentTokens {
        modal: ModalTokens {
            title: Color::Rgb(0xf6, 0xf0, 0xe8),
            hint: Color::Rgb(0x7b, 0xe0, 0x73),
            border: Color::Rgb(0xd8, 0x2a, 0x1f),
            border_highlight: Color::Rgb(0xff, 0xe0, 0x66),
        },
        navigation: NavigationTokens {
            key_chip_bg: Color::Rgb(0x1a, 0x45, 0x5e),
            key_chip_fg: Color::Rgb(0xff, 0xe0, 0x66),
            section_header: Color::Rgb(0x2f, 0xc4, 0xb2),
            scrollbar_active: Color::Rgb(0x2f, 0xc4, 0xb2),
            scrollbar_inactive: Color::Rgb(0x5d, 0x62, 0x74),
            tab_active: Color::Rgb(0x2f, 0xc4, 0xb2),
            tab_inactive: Color::Rgb(0x92, 0xb3, 0xc2),
            active_indicator: Color::Rgb(0x2f, 0xc4, 0xb2),
        },
        editor: EditorTokens {
            current_line_bg: Color::Rgb(0x1d, 0x2d, 0x3f),
            completion_selected_bg: Color::Rgb(0x2d, 0x5d, 0x46),
        },
        table: TableTokens {
            result_row_active_bg: Color::Rgb(0x2b, 0x32, 0x54),
            result_cell_active_bg: Color::Rgb(0x3a, 0x44, 0x6e),
            cell_edit_fg: Color::Rgb(0xff, 0xe0, 0x66),
            staged_delete_bg: Color::Rgb(0x4a, 0x1f, 0x1f),
            staged_delete_fg: Color::Rgb(0xff, 0x7a, 0x59),
            striped_row_bg: Color::Rgb(0x1d, 0x21, 0x2b),
        },
        feedback: FeedbackTokens {
            yank_flash_bg: Color::Rgb(0xff, 0xc8, 0x57),
            yank_flash_fg: Color::Rgb(0x14, 0x17, 0x21),
            note_text: Color::Rgb(0x92, 0xb3, 0xc2),
        },
        syntax: SyntaxTokens {
            sql_keyword: Color::Rgb(0x7d, 0xc4, 0xff),
            sql_string: Color::Rgb(0x9b, 0xf0, 0x8f),
            sql_number: Color::Rgb(0xff, 0xb8, 0x6b),
            sql_comment: Color::Rgb(0x7c, 0x8a, 0xa5),
            sql_operator: Color::Rgb(0x5e, 0xe0, 0xd5),
            sql_text: Color::Rgb(0xf6, 0xf0, 0xe8),
        },
    },
};

pub fn palette_for(theme_id: ThemeId) -> &'static ThemePalette {
    match theme_id {
        ThemeId::Default => &DEFAULT_THEME,
        ThemeId::Light => &LIGHT_THEME,
    }
}

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

    #[test]
    fn palette_for_default_returns_default_theme() {
        assert_eq!(palette_for(ThemeId::Default), &DEFAULT_THEME);
    }

    #[test]
    fn palette_for_light_returns_light_theme() {
        assert_eq!(palette_for(ThemeId::Light), &LIGHT_THEME);
    }

    #[test]
    fn panel_border_style_prefers_focus_over_highlight() {
        let style = DEFAULT_THEME.panel_border_style(true, true);

        assert_eq!(style.fg, Some(DEFAULT_THEME.semantic.surface.focus_border));
    }

    #[test]
    fn picker_selected_style_uses_selected_colors() {
        let style = DEFAULT_THEME.picker_selected_style();

        assert_eq!(
            style.bg,
            Some(DEFAULT_THEME.component.editor.completion_selected_bg)
        );
        assert_eq!(style.fg, Some(DEFAULT_THEME.semantic.text.primary));
        assert!(style.add_modifier.contains(Modifier::BOLD));
    }

    #[test]
    fn modal_input_border_style_prefers_error_over_focus() {
        let style = DEFAULT_THEME.modal_input_border_style(true, true);

        assert_eq!(style.fg, Some(DEFAULT_THEME.semantic.status.error));
    }

    #[test]
    fn status_style_uses_requested_tone() {
        let style = DEFAULT_THEME.status_style(StatusTone::Warning);

        assert_eq!(style.fg, Some(DEFAULT_THEME.semantic.status.warning));
    }

    #[test]
    fn modal_hint_style_uses_hint_token_without_bold() {
        let style = DEFAULT_THEME.modal_hint_style();

        assert_eq!(style.fg, Some(DEFAULT_THEME.component.modal.hint));
        assert!(!style.add_modifier.contains(Modifier::BOLD));
    }

    #[test]
    fn modal_border_style_uses_component_modal_border() {
        let style = DEFAULT_THEME.modal_border_style();

        assert_eq!(style.fg, Some(DEFAULT_THEME.component.modal.border));
    }

    #[test]
    fn block_cursor_style_uses_semantic_cursor_colors() {
        let style = DEFAULT_THEME.block_cursor_style();

        assert_eq!(style.bg, Some(DEFAULT_THEME.semantic.cursor.bg));
        assert_eq!(style.fg, Some(DEFAULT_THEME.semantic.cursor.text_fg));
    }
}
