//! Yali-RS görsel özelleştirme (branding) yapılandırması.
//!
//! `branding.toml` dosyasını okur ve tüm sabit kodlanmış görsel yollarını
//! çalışma zamanında çözümler. Geliştiriciler yali-rs koduna dokunmadan
//! yalnızca `branding.toml` ile logo, slayt görseli ve renk değiştirebilir.
#![allow(dead_code)]

use serde::Deserialize;
use std::collections::HashMap;

#[derive(Clone, Debug, Default, Deserialize)]
pub struct BrandingConfig {
    #[serde(default)]
    pub general: GeneralConfig,
    #[serde(default)]
    pub slides: SlidesConfig,
    #[serde(default)]
    pub theme: ThemeConfig,
    #[serde(default)]
    pub oem: OemConfig,
}

// ── [general] ────────────────────────────────────────────────────────────────

#[derive(Clone, Debug, Deserialize)]
pub struct GeneralConfig {
    /// Kurulum penceresinin başlığı.
    #[serde(default = "default_title")]
    pub title: String,

    /// Sol kenar çubuğunda gösterilen dağıtım ismi.
    #[serde(default = "default_subtitle")]
    pub subtitle: String,

    /// Sol kenar çubuğu için Yali logosu dosya yolu.
    #[serde(default = "default_yali_logo")]
    pub yali_logo: String,

    /// Kurulum ana sayfasında gösterilen PisiLinux logosu (koyu tema).
    #[serde(default = "default_pisi_logo_dark")]
    pub pisi_logo_dark: String,

    /// Kurulum ana sayfasında gösterilen PisiLinux logosu (açık tema).
    #[serde(default = "default_pisi_logo_light")]
    pub pisi_logo_light: String,
}

impl Default for GeneralConfig {
    fn default() -> Self {
        Self {
            title:          default_title(),
            subtitle:       default_subtitle(),
            yali_logo:      default_yali_logo(),
            pisi_logo_dark: default_pisi_logo_dark(),
            pisi_logo_light: default_pisi_logo_light(),
        }
    }
}

// ── [slides] ─────────────────────────────────────────────────────────────────

/// Tek bir slaytın içeriği.
#[derive(Clone, Debug, Default, Deserialize)]
pub struct SlideItem {
    /// [slides.icons] tablosundaki ikon anahtar adı.
    pub icon: String,
    /// Slayt başlığı.
    pub title: String,
    /// Slayt açıklama metni.
    pub description: String,
    /// Yalnızca bu masaüstü ortamında göster (boş = hepsinde).
    /// Örnek: "xfce", "kde", "gnome"
    #[serde(default)]
    pub desktop: String,
}

#[derive(Clone, Debug, Default, Deserialize)]
pub struct SlidesConfig {
    /// Slayt geçiş süresi (saniye).
    #[serde(default = "default_interval")]
    pub interval_secs: u64,

    /// Slayt ikonu anahtar sözcüğü → dosya yolu eşlemesi.
    #[serde(default)]
    pub icons: HashMap<String, String>,

    /// branding.toml içinde [[slides.items]] ile tanımlanan slayt listesi.
    /// Boşsa slideshow.rs içindeki sabit slaytlar kullanılır.
    #[serde(default)]
    pub items: Vec<SlideItem>,
}

// ── [theme] ──────────────────────────────────────────────────────────────────

#[derive(Clone, Debug, Deserialize)]
pub struct ThemeConfig {
    #[serde(default = "default_primary")]
    pub primary: String,
    #[serde(default = "default_accent")]
    pub accent: String,
    #[serde(default = "default_background")]
    pub background: String,
    #[serde(default = "default_text")]
    pub text: String,
}

impl Default for ThemeConfig {
    fn default() -> Self {
        Self {
            primary:    default_primary(),
            accent:     default_accent(),
            background: default_background(),
            text:       default_text(),
        }
    }
}

// ── [oem] ────────────────────────────────────────────────────────────────────

#[derive(Clone, Debug, Default, Deserialize)]
pub struct OemConfig {
    #[serde(default)]
    pub enabled: bool,
    #[serde(default)]
    #[allow(dead_code)]
    pub skip_steps: Vec<usize>,
    #[serde(default)]
    pub default_username: String,
    #[serde(default = "default_hostname")]
    pub default_hostname: String,
    #[serde(default)]
    pub default_password: String,
}

// ── Varsayılan değerler ───────────────────────────────────────────────────────

fn default_title()          -> String { "PisiLinux Install".to_string() }
fn default_subtitle()       -> String { "PiSi GNU/LINUX".to_string() }
fn default_yali_logo()      -> String { "assets/icons/YALI_icon_DARK.png".to_string() }
fn default_pisi_logo_dark()  -> String { "assets/icons/YALI_icon_DARK.png".to_string() }
fn default_pisi_logo_light() -> String { "assets/icons/YALI_icon_DARK.png".to_string() }
fn default_interval()       -> u64   { 6 }
fn default_primary()        -> String { "#1a73e8".to_string() }
fn default_accent()         -> String { "#34a853".to_string() }
fn default_background()     -> String { "#181824".to_string() }
fn default_text()           -> String { "#e2e8f0".to_string() }
fn default_hostname()       -> String { "pisi-oem".to_string() }

// ── Yükleme ──────────────────────────────────────────────────────────────────

impl BrandingConfig {
    /// `branding.toml` dosyasını arar ve yükler.
    ///
    /// Arama sırası:
    /// 1. `/etc/yali/branding.toml`
    /// 2. `/usr/share/yali/branding.toml`
    /// 3. Çalışma dizinindeki `branding.toml`
    pub fn load() -> Self {
        let paths = [
            "/etc/yali/branding.toml",
            "/usr/share/yali/branding.toml",
            "branding.toml",
        ];
        let mut config = BrandingConfig::default();
        for path in &paths {
            if let Ok(content) = std::fs::read_to_string(path) {
                match toml::from_str(&content) {
                    Ok(cfg) => { config = cfg; break; }
                    Err(e)  => eprintln!("[branding] {}: {}", path, e),
                }
            }
        }

        // slides/slides.toml varsa onu da yükle (öncelikli)
        if let Some(content) = std::fs::read_to_string("slides/slides.toml").ok() {
            if let Ok(slides) = toml::from_str::<SlidesConfig>(&content) {
                if !slides.icons.is_empty() {
                    config.slides.icons = slides.icons;
                }
                if !slides.items.is_empty() {
                    config.slides.items = slides.items;
                }
                if slides.interval_secs > 0 {
                    config.slides.interval_secs = slides.interval_secs;
                }
            }
        }

        config
    }

    /// Belirtilen dile ait `branding_{lang}.toml` dosyasını arar ve yükler.
    /// Bulunamazsa varsayılan `branding.toml` dosyasına geri döner.
    /// Yükleme sonrası `slides/slides_{lang}.toml` varsa slides verilerini da buradan alır.
    pub fn load_for_lang(lang: &str) -> Self {
        let mut config = {
            let lang_paths = [
                format!("/etc/yali/branding_{}.toml", lang),
                format!("/usr/share/yali/branding_{}.toml", lang),
                format!("branding_{}.toml", lang),
            ];
            let mut found = None;
            for path in &lang_paths {
                if let Ok(content) = std::fs::read_to_string(path) {
                    match toml::from_str(&content) {
                        Ok(cfg) => { found = Some(cfg); break; }
                        Err(e)  => eprintln!("[branding] {}: {}", path, e),
                    }
                }
            }
            found.unwrap_or_else(Self::load)
        };

        // Harici slides dosyasını dene (slides/slides_{lang}.toml)
        if let Some(slides) = Self::load_external_slides(lang) {
            if !slides.icons.is_empty() {
                config.slides.icons = slides.icons;
            }
            if !slides.items.is_empty() {
                config.slides.items = slides.items;
            }
            if slides.interval_secs > 0 {
                config.slides.interval_secs = slides.interval_secs;
            }
        }

        config
    }

    /// `slides/slides_{lang}.toml` veya `slides/slides.toml` dosyasını yükler.
    fn load_external_slides(lang: &str) -> Option<SlidesConfig> {
        let paths = [
            format!("slides/slides_{}.toml", lang),
            "slides/slides.toml".to_string(),
        ];
        for path in &paths {
            if let Ok(content) = std::fs::read_to_string(path) {
                match toml::from_str(&content) {
                    Ok(cfg) => return Some(cfg),
                    Err(e) => eprintln!("[slides] {}: {}", path, e),
                }
            }
        }
        None
    }

    /// İkon adına göre dosya yolunu döner.
    ///
    /// Koyu/açık temaya duyarlı `pisilogo` ikonu için `is_dark` parametresi
    /// kullanılır; diğer ikonlar için görmezden gelinir.
    pub fn icon_path(&self, icon: &str, is_dark: bool) -> Option<String> {
        // pisilogo özel durumu: tema bazlı iki ayrı anahtar
        if icon == "pisilogo" {
            let key = if is_dark { "pisi_logo_dark" } else { "pisi_logo_light" };
            return self.slides.icons.get(key).cloned();
        }
        self.slides.icons.get(icon).cloned()
    }

    /// Sol kenar çubuğu (Yali) logosu için `file://` URI döner.
    pub fn yali_logo_uri(&self) -> String {
        path_to_file_uri(&self.general.yali_logo)
    }

    /// Ana sayfa PisiLinux logosu (koyu tema) için `file://` URI döner.
    pub fn pisi_logo_dark_uri(&self) -> String {
        path_to_file_uri(&self.general.pisi_logo_dark)
    }

    /// Ana sayfa PisiLinux logosu (açık tema) için `file://` URI döner.
    pub fn pisi_logo_light_uri(&self) -> String {
        path_to_file_uri(&self.general.pisi_logo_light)
    }
}

/// Göreli veya mutlak dosya yolunu `egui::Image::from_uri` için uygun
/// `file://` URI formatına çevirir.
pub fn path_to_file_uri(path: &str) -> String {
    if path.starts_with("file://") || path.starts_with("http") {
        return path.to_string();
    }
    if std::path::Path::new(path).is_absolute() {
        return format!("file://{}", path);
    }
    
    // Göreli yolları sırasıyla ara:
    // 1. Çalışma dizini (CWD)
    // 2. /usr/share/yali/
    // 3. /etc/yali/
    let cwd = std::env::current_dir().unwrap_or_default();
    let cwd_path = cwd.join(path);
    if cwd_path.exists() {
        return format!("file://{}", cwd_path.display());
    }

    let usr_path = std::path::Path::new("/usr/share/yali").join(path);
    if usr_path.exists() {
        return format!("file://{}", usr_path.display());
    }

    let etc_path = std::path::Path::new("/etc/yali").join(path);
    if etc_path.exists() {
        return format!("file://{}", etc_path.display());
    }

    // Hiçbiri bulunamazsa varsayılan olarak CWD yolunu döner (hata/fallback takibi için)
    format!("file://{}", cwd_path.display())
}
