// SPDX-License-Identifier: GPL-3.0-or-later
//! Angus Software brand color integration for Temperlux.
//!
//! Maps all Angus Material 3 design tokens to libadwaita's color system.
//! Uses @define-color + CSS custom properties at USER priority.
//!
//! GTK_THEME is ignored by libadwaita — CssProvider at USER priority
//! is the correct approach and overrides ALL libadwaita defaults.

use angus_colors::{angus, to_hex};

fn pick<T: Copy>(is_dark: bool, light: T, dark: T) -> T {
    if is_dark { dark } else { light }
}

fn brand_css(is_dark: bool) -> String {
    let primary = to_hex(pick(is_dark, angus::standard::light::PRIMARY, angus::standard::dark::PRIMARY));
    let on_primary = to_hex(pick(is_dark, angus::standard::light::ON_PRIMARY, angus::standard::dark::ON_PRIMARY));
    let error = to_hex(pick(is_dark, angus::standard::light::ERROR, angus::standard::dark::ERROR));
    let on_error = to_hex(pick(is_dark, angus::standard::light::ON_ERROR, angus::standard::dark::ON_ERROR));
    let background = to_hex(pick(is_dark, angus::standard::light::BACKGROUND, angus::standard::dark::BACKGROUND));
    let on_background = to_hex(pick(is_dark, angus::standard::light::ON_BACKGROUND, angus::standard::dark::ON_BACKGROUND));
    let surface = to_hex(pick(is_dark, angus::standard::light::SURFACE, angus::standard::dark::SURFACE));
    let on_surface = to_hex(pick(is_dark, angus::standard::light::ON_SURFACE, angus::standard::dark::ON_SURFACE));
    let on_surface_variant = to_hex(pick(is_dark, angus::standard::light::ON_SURFACE_VARIANT, angus::standard::dark::ON_SURFACE_VARIANT));
    let outline = to_hex(pick(is_dark, angus::standard::light::OUTLINE, angus::standard::dark::OUTLINE));
    let outline_variant = to_hex(pick(is_dark, angus::standard::light::OUTLINE_VARIANT, angus::standard::dark::OUTLINE_VARIANT));
    let surface_container = to_hex(pick(is_dark, angus::standard::light::SURFACE_CONTAINER, angus::standard::dark::SURFACE_CONTAINER));
    let surface_container_high = to_hex(pick(is_dark, angus::standard::light::SURFACE_CONTAINER_HIGH, angus::standard::dark::SURFACE_CONTAINER_HIGH));
    let surface_container_highest = to_hex(pick(is_dark, angus::standard::light::SURFACE_CONTAINER_HIGHEST, angus::standard::dark::SURFACE_CONTAINER_HIGHEST));

    format!(
        r#"/* Angus Software — full design token integration */

/* === ACCENT === */
@define-color accent_bg_color {primary};
@define-color accent_fg_color {on_primary};
@define-color accent_color {primary};

/* === DESTRUCTIVE / ERROR === */
@define-color destructive_bg_color {error};
@define-color destructive_fg_color {on_error};
@define-color destructive_color {error};
@define-color error_bg_color {error};
@define-color error_fg_color {on_error};
@define-color error_color {error};

/* === WINDOW === */
@define-color window_bg_color {background};
@define-color window_fg_color {on_background};

/* === VIEW === */
@define-color view_bg_color {surface};
@define-color view_fg_color {on_surface};

/* === HEADERBAR === */
@define-color headerbar_bg_color {surface_container};
@define-color headerbar_fg_color {on_surface};
@define-color headerbar_border_color {on_surface_variant};
@define-color headerbar_backdrop_color {background};
@define-color headerbar_shade_color {outline_variant};
@define-color headerbar_darker_shade_color {outline_variant};

/* === SIDEBAR === */
@define-color sidebar_bg_color {surface_container};
@define-color sidebar_fg_color {on_surface};
@define-color sidebar_backdrop_color {surface_container_high};
@define-color sidebar_shade_color {outline_variant};
@define-color sidebar_border_color {outline};
@define-color secondary_sidebar_bg_color {surface_container};
@define-color secondary_sidebar_fg_color {on_surface};
@define-color secondary_sidebar_backdrop_color {surface_container_high};
@define-color secondary_sidebar_shade_color {outline_variant};
@define-color secondary_sidebar_border_color {outline};

/* === CARDS === */
@define-color card_bg_color {surface_container_high};
@define-color card_fg_color {on_surface};
@define-color card_shade_color {outline_variant};

/* === DIALOGS === */
@define-color dialog_bg_color {background};
@define-color dialog_fg_color {on_background};

/* === POPOVERS === */
@define-color popover_bg_color {surface_container_highest};
@define-color popover_fg_color {on_surface};
@define-color popover_shade_color {outline_variant};

/* === MISC === */
@define-color thumbnail_bg_color {surface_container_high};
@define-color thumbnail_fg_color {on_surface};
@define-color shade_color {outline_variant};

/* === SELECTION === */
@define-color theme_selected_bg_color {primary};
@define-color theme_selected_fg_color {on_primary};
@define-color theme_unfocused_selected_bg_color {primary};
@define-color theme_unfocused_selected_fg_color {on_primary};

/* === CSS CUSTOM PROPERTIES === */
window {{
  --accent-bg-color: {primary};
  --accent-fg-color: {on_primary};
  --accent-color: {primary};
  --destructive-bg-color: {error};
  --destructive-fg-color: {on_error};
  --destructive-color: {error};
  --error-bg-color: {error};
  --error-fg-color: {on_error};
  --error-color: {error};
  --window-bg-color: {background};
  --window-fg-color: {on_background};
  --view-bg-color: {surface};
  --view-fg-color: {on_surface};
  --headerbar-bg-color: {surface_container};
  --headerbar-fg-color: {on_surface};
  --headerbar-border-color: {on_surface_variant};
  --headerbar-backdrop-color: {background};
  --headerbar-shade-color: {outline_variant};
  --headerbar-darker-shade-color: {outline_variant};
  --sidebar-bg-color: {surface_container};
  --sidebar-fg-color: {on_surface};
  --sidebar-backdrop-color: {surface_container_high};
  --sidebar-shade-color: {outline_variant};
  --sidebar-border-color: {outline};
  --card-bg-color: {surface_container_high};
  --card-fg-color: {on_surface};
  --card-shade-color: {outline_variant};
  --dialog-bg-color: {background};
  --dialog-fg-color: {on_background};
  --popover-bg-color: {surface_container_highest};
  --popover-fg-color: {on_surface};
  --popover-shade-color: {outline_variant};
  --shade-color: {outline_variant};
}}

/* === LINKS === */
link {{ color: {primary}; }}
link:visited {{ color: {error}; }}
"#
    )
}

use std::cell::RefCell;

thread_local! {
    static ACTIVE_PROVIDER: RefCell<Option<gtk4::CssProvider>> = const { RefCell::new(None) };
    static LIGHT_THEME: RefCell<crate::settings::ColorTheme> = const { RefCell::new(crate::settings::ColorTheme::AngusLight) };
    static DARK_THEME: RefCell<crate::settings::ColorTheme> = const { RefCell::new(crate::settings::ColorTheme::AngusDark) };
}

/// Get the CSS string for a specific theme.
/// Angus generates dynamically; community themes use embedded CSS.
fn theme_css(theme: crate::settings::ColorTheme, _is_dark: bool) -> String {
    match theme {
        crate::settings::ColorTheme::AngusLight => brand_css(false),
        crate::settings::ColorTheme::AngusDark => brand_css(true),
        _ => theme.css().to_string(),
    }
}

/// Get the CSS for the currently active theme (based on light/dark state).
fn active_css(is_dark: bool) -> String {
    if is_dark {
        let theme = DARK_THEME.with(|t| *t.borrow());
        theme_css(theme, true)
    } else {
        let theme = LIGHT_THEME.with(|t| *t.borrow());
        theme_css(theme, false)
    }
}

/// Load the color theme CSS provider into the default display at USER priority.
/// Automatically reloads CSS when libadwaita switches between light and dark.
pub fn load_brand_theme() {
    let is_dark = libadwaita::StyleManager::default().is_dark();

    let provider = gtk4::CssProvider::new();
    provider.load_from_data(&active_css(is_dark));

    if let Some(display) = gtk4::gdk::Display::default() {
        gtk4::style_context_add_provider_for_display(
            &display,
            &provider,
            gtk4::STYLE_PROVIDER_PRIORITY_USER,
        );
    }

    ACTIVE_PROVIDER.with(|p| *p.borrow_mut() = Some(provider.clone()));

    // Reload CSS when libadwaita switches light/dark
    libadwaita::StyleManager::default().connect_dark_notify(move |mgr| {
        provider.load_from_data(&active_css(mgr.is_dark()));
    });
}

/// Apply the light and dark theme selections.
/// Updates the CSS provider immediately with whichever theme is active.
pub fn apply_color_themes(light: crate::settings::ColorTheme, dark: crate::settings::ColorTheme) {
    LIGHT_THEME.with(|t| *t.borrow_mut() = light);
    DARK_THEME.with(|t| *t.borrow_mut() = dark);

    let is_dark = libadwaita::StyleManager::default().is_dark();
    let css = active_css(is_dark);

    ACTIVE_PROVIDER.with(|p| {
        if let Some(provider) = p.borrow().as_ref() {
            provider.load_from_data(&css);
        }
    });
}

/// Apply the theme mode from settings to libadwaita's StyleManager.
/// This triggers the dark_notify signal which reloads the CSS provider
/// with the correct light or dark Angus color tokens.
pub fn apply_theme_mode(mode: crate::settings::ThemeMode) {
    let style_mgr = libadwaita::StyleManager::default();
    let scheme = match mode {
        crate::settings::ThemeMode::System => libadwaita::ColorScheme::Default,
        crate::settings::ThemeMode::Light => libadwaita::ColorScheme::ForceLight,
        crate::settings::ThemeMode::Dark => libadwaita::ColorScheme::ForceDark,
    };
    style_mgr.set_color_scheme(scheme);
}

pub fn primary_hex(is_dark: bool) -> String {
    to_hex(pick(is_dark, angus::standard::light::PRIMARY, angus::standard::dark::PRIMARY))
}

pub fn on_primary_hex(is_dark: bool) -> String {
    to_hex(pick(is_dark, angus::standard::light::ON_PRIMARY, angus::standard::dark::ON_PRIMARY))
}

pub fn error_hex(is_dark: bool) -> String {
    to_hex(pick(is_dark, angus::standard::light::ERROR, angus::standard::dark::ERROR))
}

pub fn surface_hex(is_dark: bool) -> String {
    to_hex(pick(is_dark, angus::standard::light::SURFACE, angus::standard::dark::SURFACE))
}
