//! Application state management
//!
//! This module provides global state management using Leptos signals and contexts.
//! Following L-SIGNALS-NOT-STATE principle, we use reactive signals instead of
//! traditional state management patterns.

use dashboard_shared::Theme;
use leptos::prelude::*;

/// Global application state context
///
/// This struct holds all application-wide reactive state that needs to be
/// shared across components. It is provided at the root level and can be
/// consumed by any child component.
#[derive(Clone, Copy)]
pub struct AppState {
    /// Current theme (light/dark)
    pub theme: RwSignal<Theme>,
    /// Optional authentication token
    #[allow(dead_code)]
    pub auth_token: RwSignal<Option<String>>,
    /// API base URL
    #[allow(dead_code)]
    pub api_url: ReadSignal<String>,
    /// WebSocket URL
    #[allow(dead_code)]
    pub ws_url: ReadSignal<Option<String>>,
}

impl AppState {
    /// Creates a new AppState with default values
    ///
    /// # Example
    ///
    /// ```ignore
    /// let state = AppState::new();
    /// provide_context(state);
    /// ```
    pub fn new() -> Self {
        let (api_url, _) = signal("http://localhost:8080".to_string());
        let (ws_url, _) = signal(Some("ws://localhost:8080/ws".to_string()));

        Self {
            theme: RwSignal::new(Theme::Light),
            auth_token: RwSignal::new(None),
            api_url,
            ws_url,
        }
    }

    /// Toggles between light and dark theme
    pub fn toggle_theme(&self) {
        self.theme.update(|theme| {
            *theme = match *theme {
                Theme::Light => Theme::Dark,
                Theme::Dark => Theme::Light,
            };
        });
    }

    /// Sets the authentication token
    #[allow(dead_code)]
    pub fn set_auth_token(&self, token: Option<String>) {
        self.auth_token.set(token);
    }

    /// Gets the current theme
    #[allow(dead_code)]
    pub fn get_theme(&self) -> Theme {
        self.theme.get()
    }

    /// Checks if user is authenticated
    #[allow(dead_code)]
    pub fn is_authenticated(&self) -> bool {
        self.auth_token.get().is_some()
    }
}

impl Default for AppState {
    fn default() -> Self {
        Self::new()
    }
}

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

    #[test]
    fn test_app_state_creation() {
        let state = AppState::new();
        assert_eq!(state.get_theme(), Theme::Light);
        assert!(!state.is_authenticated());
    }

    #[test]
    fn test_theme_toggle() {
        let state = AppState::new();
        assert_eq!(state.get_theme(), Theme::Light);

        state.toggle_theme();
        assert_eq!(state.get_theme(), Theme::Dark);

        state.toggle_theme();
        assert_eq!(state.get_theme(), Theme::Light);
    }

    #[test]
    fn test_auth_token() {
        let state = AppState::new();
        assert!(!state.is_authenticated());

        state.set_auth_token(Some("test-token".to_string()));
        assert!(state.is_authenticated());

        state.set_auth_token(None);
        assert!(!state.is_authenticated());
    }
}
