use gloo_storage::{LocalStorage, SessionStorage, Storage};
use serde::{Deserialize, Serialize};

/// Local storage utilities for persistent data
pub struct LocalStorageManager;

impl LocalStorageManager {
    pub fn set<T: Serialize>(key: &str, value: &T) -> Result<(), String> {
        LocalStorage::set(key, value)
            .map_err(|e| format!("Failed to save to localStorage: {:?}", e))
    }

    pub fn get<T: for<'de> Deserialize<'de>>(key: &str) -> Option<T> {
        LocalStorage::get(key).ok()
    }

    pub fn remove(key: &str) {
        LocalStorage::delete(key);
    }

    pub fn clear() {
        LocalStorage::clear();
    }

    pub fn has_key(key: &str) -> bool {
        LocalStorage::get::<String>(key).is_ok()
    }
}

/// Session storage utilities for temporary data
pub struct SessionStorageManager;

impl SessionStorageManager {
    pub fn set<T: Serialize>(key: &str, value: &T) -> Result<(), String> {
        SessionStorage::set(key, value)
            .map_err(|e| format!("Failed to save to sessionStorage: {:?}", e))
    }

    pub fn get<T: for<'de> Deserialize<'de>>(key: &str) -> Option<T> {
        SessionStorage::get(key).ok()
    }

    pub fn remove(key: &str) {
        SessionStorage::delete(key);
    }

    pub fn clear() {
        SessionStorage::clear();
    }

    pub fn has_key(key: &str) -> bool {
        SessionStorage::get::<String>(key).is_ok()
    }
}

/// Storage keys used throughout the application
pub struct StorageKeys;

impl StorageKeys {
    pub const AUTH_TOKEN: &'static str = "auth_token";
    pub const USER_INFO: &'static str = "user_info";
    pub const THEME: &'static str = "theme";
    pub const APP_STATE: &'static str = "app_state";
    pub const SIDEBAR_COLLAPSED: &'static str = "sidebar_collapsed";
    pub const DASHBOARD_LAYOUT: &'static str = "dashboard_layout";
    pub const USER_PREFERENCES: &'static str = "user_preferences";
    pub const RECENT_SEARCHES: &'static str = "recent_searches";
    pub const BOOKMARKS: &'static str = "bookmarks";
}

/// User preferences stored in localStorage
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct UserPreferences {
    pub theme: String,
    pub sidebar_collapsed: bool,
    pub dashboard_refresh_interval: u32, // seconds
    pub notifications_enabled: bool,
    pub auto_refresh: bool,
    pub timezone: Option<String>,
    pub date_format: String,
    pub time_format: String,
}

impl Default for UserPreferences {
    fn default() -> Self {
        Self {
            theme: "auto".to_string(),
            sidebar_collapsed: false,
            dashboard_refresh_interval: 30,
            notifications_enabled: true,
            auto_refresh: true,
            timezone: None,
            date_format: "YYYY-MM-DD".to_string(),
            time_format: "HH:mm:ss".to_string(),
        }
    }
}

impl UserPreferences {
    pub fn load() -> Self {
        LocalStorageManager::get(StorageKeys::USER_PREFERENCES).unwrap_or_default()
    }

    pub fn save(&self) {
        let _ = LocalStorageManager::set(StorageKeys::USER_PREFERENCES, self);
    }

    pub fn reset() {
        LocalStorageManager::remove(StorageKeys::USER_PREFERENCES);
    }
}

/// Recent searches for quick access
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct RecentSearches {
    pub searches: Vec<String>,
    pub max_items: usize,
}

impl Default for RecentSearches {
    fn default() -> Self {
        Self {
            searches: Vec::new(),
            max_items: 10,
        }
    }
}

impl RecentSearches {
    pub fn load() -> Self {
        LocalStorageManager::get(StorageKeys::RECENT_SEARCHES).unwrap_or_default()
    }

    pub fn add_search(&mut self, search: String) {
        // Remove if already exists
        self.searches.retain(|s| s != &search);

        // Add to front
        self.searches.insert(0, search);

        // Trim to max items
        if self.searches.len() > self.max_items {
            self.searches.truncate(self.max_items);
        }

        self.save();
    }

    pub fn remove_search(&mut self, search: &str) {
        self.searches.retain(|s| s != search);
        self.save();
    }

    pub fn clear(&mut self) {
        self.searches.clear();
        self.save();
    }

    pub fn save(&self) {
        let _ = LocalStorageManager::set(StorageKeys::RECENT_SEARCHES, self);
    }
}

/// Bookmarks for quick access to resources
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Bookmark {
    pub id: String,
    pub title: String,
    pub url: String,
    pub description: Option<String>,
    pub tags: Vec<String>,
    pub created_at: chrono::DateTime<chrono::Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
pub struct BookmarkManager {
    pub bookmarks: Vec<Bookmark>,
}

impl BookmarkManager {
    pub fn load() -> Self {
        LocalStorageManager::get(StorageKeys::BOOKMARKS).unwrap_or_default()
    }

    pub fn add_bookmark(&mut self, bookmark: Bookmark) {
        self.bookmarks.push(bookmark);
        self.save();
    }

    pub fn remove_bookmark(&mut self, id: &str) {
        self.bookmarks.retain(|b| b.id != id);
        self.save();
    }

    pub fn get_bookmarks_by_tag(&self, tag: &str) -> Vec<&Bookmark> {
        self.bookmarks
            .iter()
            .filter(|b| b.tags.contains(&tag.to_string()))
            .collect()
    }

    pub fn save(&self) {
        let _ = LocalStorageManager::set(StorageKeys::BOOKMARKS, self);
    }
}
