//! State Management Example
//!
//! Demonstrates configuration-driven client state management patterns
//! and how to extend them with custom reactive patterns when needed.

use std::collections::HashMap;

use leptos::prelude::*;
use rustelo_client::state::{GlobalState, LocalState, StateConfig, StateProvider};
use serde::{Deserialize, Serialize};

/// Configuration-Driven State Management Example
///
/// This example shows how Rustelo's client state management works:
/// 1. Define state configuration in TOML files (90%)
/// 2. Generate reactive state providers automatically
/// 3. Extend with custom state logic when needed (10%)
fn main() {
    println!("🎯 RUSTELO CLIENT STATE MANAGEMENT EXAMPLE");
    println!("==========================================");
    println!();

    println!("This example demonstrates Rustelo's configuration-driven state management:");
    println!("• TOML configuration defines what state to manage");
    println!("• Reactive providers generated automatically");
    println!("• Custom state logic for complex requirements");
    println!();

    demonstrate_toml_driven_state();
    println!();

    demonstrate_generated_providers();
    println!();

    demonstrate_custom_state_extensions();
    println!();

    demonstrate_state_persistence();
    println!();

    demonstrate_state_synchronization();
}

/// Step 1: TOML Configuration → State Management
///
/// Shows how TOML configuration defines what state the client manages
fn demonstrate_toml_driven_state() {
    println!("📋 STEP 1: TOML CONFIGURATION → STATE MANAGEMENT");
    println!("===============================================");
    println!();

    println!("📝 File: site/config/client-state.toml");
    let toml_config = r#"
[global_state]
theme = { type = "persisted", default = "light", storage = "localStorage" }
language = { type = "reactive", default = "en", sync = "url" }
auth = { type = "secure", default = "unauthenticated", encryption = true }
notifications = { type = "transient", default = [] }

[page_state]
[page_state.dashboard]
filters = { type = "local", default = {} }
sort_order = { type = "persisted", default = "date_desc" }
chart_config = { type = "local", default = { type = "line", period = "7d" } }

[page_state.profile]
edit_mode = { type = "local", default = false }
unsaved_changes = { type = "transient", default = false }

[state_sync]
cross_tab_sync = true
server_sync_enabled = false
offline_queue = true
conflict_resolution = "client_wins"
"#;

    println!("{}", toml_config);
    println!();

    println!("⚙️  Generated State Management:");
    println!("   • ThemeProvider (persisted in localStorage)");
    println!("   • LanguageProvider (reactive, synced to URL)");
    println!("   • AuthProvider (secure, encrypted storage)");
    println!("   • NotificationProvider (transient, in-memory)");
    println!("   • PageStateProvider (per-page local state)");
    println!("   • StateSyncProvider (cross-tab synchronization)");
}

/// Step 2: Generated State Providers
///
/// Shows the reactive state providers that get generated from TOML
/// configuration
fn demonstrate_generated_providers() {
    println!("🏗️ STEP 2: GENERATED STATE PROVIDERS");
    println!("===================================");
    println!();

    println!("📦 Generated Provider Structure:");

    let generated_example = r#"
// Generated from your client-state.toml configuration
#[component]
pub fn AppStateProviders(children: Children) -> impl IntoView {
    view! {
        // Global state providers (from [global_state])
        <ThemeProvider default="light" storage="localStorage">
            <LanguageProvider default="en" sync="url">
                <AuthProvider default="unauthenticated" secure=true>
                    <NotificationProvider>
                        // Page-specific providers (from [page_state])
                        <PageStateProvider>
                            // Sync providers (from [state_sync])
                            <StateSyncProvider
                                cross_tab=true
                                offline_queue=true
                                conflict_resolution="client_wins">
                                {children()}
                            </StateSyncProvider>
                        </PageStateProvider>
                    </NotificationProvider>
                </AuthProvider>
            </LanguageProvider>
        </ThemeProvider>
    }
}

// Generated hooks for each state type
pub fn use_theme_state() -> ThemeState { /* ... */ }
pub fn use_language_state() -> LanguageState { /* ... */ }
pub fn use_auth_state() -> AuthState { /* ... */ }
pub fn use_notification_state() -> NotificationState { /* ... */ }
pub fn use_page_state<T>() -> PageState<T> { /* ... */ }
"#;

    println!("{}", generated_example);
    println!();

    println!("🎯 Usage in Components:");
    let usage_example = r#"
#[component]
pub fn DashboardComponent() -> impl IntoView {
    // Use generated state hooks
    let theme = use_theme_state();
    let language = use_language_state();
    let auth = use_auth_state();

    // Page-specific state (automatically scoped to dashboard)
    let dashboard_state = use_page_state::<DashboardState>();

    view! {
        <div class={move || format!("dashboard theme-{}", theme.current())}>
            <h1>{move || language.t("dashboard-title")}</h1>

            // State automatically persists and syncs
            <FilterPanel filters=dashboard_state.filters />
            <ChartDisplay config=dashboard_state.chart_config />
        </div>
    }
}
"#;

    println!("{}", usage_example);
}

/// Step 3: Custom State Extensions
///
/// Shows how to extend generated state providers with custom logic (10% case)
fn demonstrate_custom_state_extensions() {
    println!("🔧 STEP 3: CUSTOM STATE EXTENSIONS");
    println!("==================================");
    println!();

    println!("For complex state requirements that TOML can't express:");
    println!();

    let custom_extension = r#"
// Custom state extension for complex business logic
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AdvancedDashboardState {
    // Generated base state from TOML
    pub base: DashboardState,

    // Custom complex state that needs special handling
    pub realtime_metrics: Vec<Metric>,
    pub user_preferences: UserPreferences,
    pub computed_insights: ComputedInsights,
    pub collaboration_state: CollaborationState,
}

#[component]
pub fn AdvancedDashboard() -> impl IntoView {
    // Use generated base state (90%)
    let base_state = use_page_state::<DashboardState>();

    // Add custom state management (10%)
    let (realtime_metrics, set_realtime_metrics) = create_signal(Vec::new());
    let (collaboration_state, set_collaboration_state) = create_signal(CollaborationState::default());

    // Custom complex state logic
    let computed_insights = create_memo(move |_| {
        let metrics = realtime_metrics.get();
        let preferences = base_state.user_preferences.get();

        // Complex computation that can't be expressed in TOML
        compute_advanced_insights(&metrics, &preferences)
    });

    // Custom state synchronization
    create_effect(move |_| {
        spawn_local(async move {
            // Sync with real-time data source
            if let Ok(new_metrics) = fetch_realtime_metrics().await {
                set_realtime_metrics.set(new_metrics);
            }

            // Sync collaboration state with other users
            if let Ok(collab_state) = fetch_collaboration_state().await {
                set_collaboration_state.set(collab_state);
            }
        });
    });

    // Custom state persistence for complex data
    create_effect(move |_| {
        let insights = computed_insights.get();
        let collab = collaboration_state.get();

        // Custom persistence logic for complex state
        spawn_local(async move {
            let _ = persist_advanced_state(&insights, &collab).await;
        });
    });

    view! {
        <div class="advanced-dashboard">
            // Base functionality from generated state
            <StandardDashboard state=base_state />

            // Custom extensions with complex state
            <RealtimeMetricsPanel metrics=realtime_metrics />
            <InsightsPanel insights=computed_insights />
            <CollaborationPanel state=collaboration_state />
        </div>
    }
}
"#;

    println!("{}", custom_extension);
}

/// Step 4: State Persistence Patterns
///
/// Shows different persistence strategies based on TOML configuration
fn demonstrate_state_persistence() {
    println!("💾 STEP 4: STATE PERSISTENCE PATTERNS");
    println!("====================================");
    println!();

    println!("Different persistence strategies from TOML configuration:");
    println!();

    let persistence_examples = r#"
// Generated persistence based on TOML config
match state_config.storage_type {
    "localStorage" => {
        // Persists across browser sessions
        let theme = LocalStorage::get("theme").unwrap_or_default();
        let sort_order = LocalStorage::get("dashboard_sort").unwrap_or_default();
    }

    "sessionStorage" => {
        // Persists for current session only
        let filters = SessionStorage::get("dashboard_filters").unwrap_or_default();
    }

    "indexedDB" => {
        // For large/complex data
        let user_data = IndexedDB::get("user_preferences").await.unwrap_or_default();
    }

    "memory" => {
        // Transient state, lost on page reload
        let notifications = in_memory_store.get("current_notifications");
    }

    "encrypted" => {
        // Encrypted sensitive data
        let auth_tokens = EncryptedStorage::get("auth_state").unwrap();
    }
}

// Automatic persistence hooks generated from config
#[hook]
pub fn use_persistent_state<T>(key: &str, default: T) -> (ReadSignal<T>, WriteSignal<T>)
where
    T: Serialize + for<'de> Deserialize<'de> + Clone + 'static
{
    let (state, set_state) = create_signal(default);

    // Load initial value from configured storage
    create_effect(move |_| {
        spawn_local(async move {
            if let Ok(stored_value) = load_from_configured_storage(key).await {
                set_state.set(stored_value);
            }
        });
    });

    // Auto-save on changes
    create_effect(move |_| {
        let current_value = state.get();
        spawn_local(async move {
            let _ = save_to_configured_storage(key, &current_value).await;
        });
    });

    (state, set_state)
}
"#;

    println!("{}", persistence_examples);
}

/// Step 5: State Synchronization
///
/// Shows cross-tab and server synchronization patterns
fn demonstrate_state_synchronization() {
    println!("🔄 STEP 5: STATE SYNCHRONIZATION");
    println!("===============================");
    println!();

    println!("Generated synchronization based on TOML config:");
    println!();

    let sync_examples = r#"
// Cross-tab synchronization (from state_sync.cross_tab_sync = true)
#[hook]
pub fn use_synced_state<T>(key: &str, default: T) -> (ReadSignal<T>, WriteSignal<T>)
where
    T: Serialize + for<'de> Deserialize<'de> + Clone + 'static
{
    let (state, set_state) = create_signal(default);

    // Listen for changes from other tabs
    create_effect(move |_| {
        let window = web_sys::window().unwrap();
        let storage_listener = Closure::wrap(Box::new(move |event: web_sys::StorageEvent| {
            if event.key().as_deref() == Some(key) {
                if let Some(new_value) = event.new_value() {
                    if let Ok(parsed) = serde_json::from_str(&new_value) {
                        set_state.set(parsed);
                    }
                }
            }
        }) as Box<dyn FnMut(_)>);

        window.add_event_listener_with_callback(
            "storage",
            storage_listener.as_ref().unchecked_ref()
        ).unwrap();

        storage_listener.forget();
    });

    // Broadcast changes to other tabs
    create_effect(move |_| {
        let current_value = state.get();
        let serialized = serde_json::to_string(&current_value).unwrap();

        web_sys::window()
            .unwrap()
            .local_storage()
            .unwrap()
            .unwrap()
            .set_item(key, &serialized)
            .unwrap();
    });

    (state, set_state)
}

// Offline queue (from state_sync.offline_queue = true)
#[component]
pub fn OfflineStateManager() -> impl IntoView {
    let (is_online, set_is_online) = create_signal(true);
    let (pending_updates, set_pending_updates) = create_signal(Vec::<StateUpdate>::new());

    // Monitor online/offline status
    create_effect(move |_| {
        let window = web_sys::window().unwrap();
        let navigator = window.navigator();
        set_is_online.set(navigator.on_line());

        let online_listener = Closure::wrap(Box::new(move |_| {
            set_is_online.set(true);
            // Process queued updates when back online
            spawn_local(async move {
                process_offline_queue().await;
            });
        }) as Box<dyn FnMut(_)>);

        let offline_listener = Closure::wrap(Box::new(move |_| {
            set_is_online.set(false);
        }) as Box<dyn FnMut(_)>);

        window.add_event_listener_with_callback("online", online_listener.as_ref().unchecked_ref()).unwrap();
        window.add_event_listener_with_callback("offline", offline_listener.as_ref().unchecked_ref()).unwrap();

        online_listener.forget();
        offline_listener.forget();
    });

    view! {
        <div class="offline-state-indicator" class:offline=move || !is_online.get()>
            {move || if is_online.get() {
                "🌐 Online"
            } else {
                format!("🔌 Offline ({} pending)", pending_updates.get().len())
            }}
        </div>
    }
}

// Conflict resolution (from state_sync.conflict_resolution = "client_wins")
async fn resolve_state_conflict<T>(
    local_state: &T,
    server_state: &T,
    last_sync_time: chrono::DateTime<chrono::Utc>
) -> T
where
    T: Clone + Serialize + for<'de> Deserialize<'de>
{
    match get_conflict_resolution_strategy() {
        ConflictResolution::ClientWins => local_state.clone(),
        ConflictResolution::ServerWins => server_state.clone(),
        ConflictResolution::LastWriteWins => {
            if local_state.last_modified > server_state.last_modified {
                local_state.clone()
            } else {
                server_state.clone()
            }
        }
        ConflictResolution::Merge => {
            // Custom merge logic based on state type
            merge_states(local_state, server_state)
        }
    }
}
"#;

    println!("{}", sync_examples);

    println!();
    println!("💡 Key State Management Principles:");
    println!("   • Configuration defines what state to manage (90%)");
    println!("   • Providers generated automatically from TOML");
    println!("   • Persistence strategy configurable per state");
    println!("   • Cross-tab sync enabled by configuration");
    println!("   • Custom logic for complex state requirements (10%)");
    println!("   • Offline queue for reliable state updates");
    println!("   • Configurable conflict resolution strategies");
}

// Example components demonstrating different state patterns

/// Theme State Management Example
#[component]
pub fn ThemeManager() -> impl IntoView {
    // Generated from theme state configuration
    let theme_state = use_theme_state();

    view! {
        <div class="theme-manager">
            <h3>"🎨 Theme Management"</h3>

            <div class="theme-controls">
                <button
                    class:active=move || theme_state.current() == "light"
                    on:click=move |_| theme_state.set("light")
                >
                    "☀️ Light"
                </button>

                <button
                    class:active=move || theme_state.current() == "dark"
                    on:click=move |_| theme_state.set("dark")
                >
                    "🌙 Dark"
                </button>

                <button
                    class:active=move || theme_state.current() == "auto"
                    on:click=move |_| theme_state.set("auto")
                >
                    "🔄 Auto"
                </button>
            </div>

            <div class="theme-info">
                <p>"Current theme: " {move || theme_state.current()}</p>
                <p>"Persisted: " {move || if theme_state.is_persisted() { "✅" } else { "❌" }}</p>
                <p>"System preference: " {move || theme_state.system_preference()}</p>
            </div>
        </div>
    }
}

/// Dashboard State Management Example
#[component]
pub fn DashboardStateDemo() -> impl IntoView {
    // Page state automatically scoped to dashboard
    let dashboard_state = use_page_state::<DashboardPageState>();

    view! {
        <div class="dashboard-state-demo">
            <h3>"📊 Dashboard State"</h3>

            <div class="state-controls">
                <div class="filter-controls">
                    <label>"Date Range:"</label>
                    <select on:change=move |ev| {
                        let value = event_target_value(&ev);
                        dashboard_state.set_date_range(value);
                    }>
                        <option value="7d">"Last 7 days"</option>
                        <option value="30d">"Last 30 days"</option>
                        <option value="90d">"Last 90 days"</option>
                    </select>
                </div>

                <div class="sort-controls">
                    <label>"Sort by:"</label>
                    <select on:change=move |ev| {
                        let value = event_target_value(&ev);
                        dashboard_state.set_sort_order(value);
                    }>
                        <option value="date_desc">"Date (newest first)"</option>
                        <option value="date_asc">"Date (oldest first)"</option>
                        <option value="value_desc">"Value (high to low)"</option>
                        <option value="value_asc">"Value (low to high)"</option>
                    </select>
                </div>
            </div>

            <div class="state-info">
                <p>"Filters: " {move || format!("{:?}", dashboard_state.filters())}</p>
                <p>"Sort: " {move || dashboard_state.sort_order()}</p>
                <p>"Auto-saved: " {move || if dashboard_state.is_dirty() { "❌" } else { "✅" }}</p>
            </div>
        </div>
    }
}

/// Custom Complex State Example
#[component]
pub fn ComplexStateDemo() -> impl IntoView {
    // Custom state for requirements TOML can't express
    let (user_activity, set_user_activity) = create_signal(UserActivity::default());
    let (collaboration_state, set_collaboration_state) =
        create_signal(HashMap::<String, CollaboratorState>::new());

    // Complex computed state
    let activity_insights = create_memo(move |_| {
        let activity = user_activity.get();
        let collaborators = collaboration_state.get();

        ActivityInsights::compute(&activity, &collaborators)
    });

    // Real-time synchronization
    create_effect(move |_| {
        spawn_local(async move {
            // Connect to real-time collaboration service
            if let Ok(mut stream) = connect_to_collaboration_service().await {
                while let Some(update) = stream.next().await {
                    match update {
                        CollaborationUpdate::UserJoined(user) => {
                            set_collaboration_state.update(|state| {
                                state.insert(user.id.clone(), user.into());
                            });
                        }
                        CollaborationUpdate::UserLeft(user_id) => {
                            set_collaboration_state.update(|state| {
                                state.remove(&user_id);
                            });
                        }
                        CollaborationUpdate::ActivityUpdate(activity) => {
                            set_user_activity.set(activity);
                        }
                    }
                }
            }
        });
    });

    view! {
        <div class="complex-state-demo">
            <h3>"🤝 Complex State Management"</h3>

            <div class="activity-panel">
                <h4>"User Activity"</h4>
                <div class="activity-stats">
                    <div class="stat">
                        <span class="label">"Actions today:"</span>
                        <span class="value">{move || user_activity.get().actions_today}</span>
                    </div>
                    <div class="stat">
                        <span class="label">"Time active:"</span>
                        <span class="value">{move || format!("{}m", user_activity.get().time_active_minutes)}</span>
                    </div>
                </div>
            </div>

            <div class="collaboration-panel">
                <h4>"Collaboration"</h4>
                <div class="collaborators">
                    {move || {
                        collaboration_state.get()
                            .iter()
                            .map(|(id, state)| {
                                view! {
                                    <div class="collaborator" data-id=id>
                                        <span class="avatar">{&state.avatar}</span>
                                        <span class="name">{&state.name}</span>
                                        <span class="status" class:online=state.is_online>
                                            {if state.is_online { "🟢" } else { "⭕" }}
                                        </span>
                                    </div>
                                }
                            })
                            .collect_view()
                    }}
                </div>
            </div>

            <div class="insights-panel">
                <h4>"Activity Insights"</h4>
                <div class="insights">
                    {move || {
                        let insights = activity_insights.get();
                        view! {
                            <div class="insight">
                                <span class="metric">"Productivity Score:"</span>
                                <span class="value">{insights.productivity_score}</span>
                            </div>
                            <div class="insight">
                                <span class="metric">"Collaboration Index:"</span>
                                <span class="value">{insights.collaboration_index}</span>
                            </div>
                            <div class="insight">
                                <span class="metric">"Focus Time:"</span>
                                <span class="value">{format!("{}%", insights.focus_time_percentage)}</span>
                            </div>
                        }
                    }}
                </div>
            </div>
        </div>
    }
}

// Supporting types and mock implementations

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
struct DashboardPageState {
    filters: HashMap<String, serde_json::Value>,
    sort_order: String,
    date_range: String,
    chart_config: ChartConfig,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
struct ChartConfig {
    chart_type: String,
    period: String,
}

impl Default for ChartConfig {
    fn default() -> Self {
        Self {
            chart_type: "line".to_string(),
            period: "7d".to_string(),
        }
    }
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
struct UserActivity {
    actions_today: u32,
    time_active_minutes: u32,
    last_action_timestamp: u64,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
struct CollaboratorState {
    name: String,
    avatar: String,
    is_online: bool,
    last_seen: u64,
}

#[derive(Clone, Debug)]
struct ActivityInsights {
    productivity_score: f64,
    collaboration_index: f64,
    focus_time_percentage: f64,
}

impl ActivityInsights {
    fn compute(
        _activity: &UserActivity,
        _collaborators: &HashMap<String, CollaboratorState>,
    ) -> Self {
        Self {
            productivity_score: 85.0,
            collaboration_index: 7.5,
            focus_time_percentage: 65.0,
        }
    }
}

enum CollaborationUpdate {
    UserJoined(User),
    UserLeft(String),
    ActivityUpdate(UserActivity),
}

#[derive(Clone)]
struct User {
    id: String,
    name: String,
    avatar: String,
}

impl From<User> for CollaboratorState {
    fn from(user: User) -> Self {
        Self {
            name: user.name,
            avatar: user.avatar,
            is_online: true,
            last_seen: js_sys::Date::now() as u64,
        }
    }
}

#[derive(Clone, Debug)]
struct StateUpdate {
    key: String,
    value: serde_json::Value,
    timestamp: u64,
}

enum ConflictResolution {
    ClientWins,
    ServerWins,
    LastWriteWins,
    Merge,
}

// Mock function implementations
fn use_theme_state() -> ThemeState {
    ThemeState::default()
}
fn use_language_state() -> LanguageState {
    LanguageState::default()
}
fn use_auth_state() -> AuthState {
    AuthState::default()
}
fn use_page_state<T>() -> PageState<T>
where
    T: Default,
{
    PageState::default()
}
async fn fetch_realtime_metrics() -> Result<Vec<Metric>, String> {
    Ok(vec![])
}
async fn fetch_collaboration_state() -> Result<CollaborationState, String> {
    Ok(CollaborationState {
        name: "".to_string(),
        avatar: "".to_string(),
        is_online: false,
        last_seen: 0,
    })
}
async fn persist_advanced_state(
    _insights: &ActivityInsights,
    _collab: &HashMap<String, CollaboratorState>,
) -> Result<(), String> {
    Ok(())
}
fn compute_advanced_insights(
    _metrics: &[Metric],
    _preferences: &UserPreferences,
) -> ActivityInsights {
    ActivityInsights::compute(&UserActivity::default(), &HashMap::new())
}
async fn load_from_configured_storage<T>(_key: &str) -> Result<T, String>
where
    T: Default,
{
    Ok(T::default())
}
async fn save_to_configured_storage<T>(_key: &str, _value: &T) -> Result<(), String> {
    Ok(())
}
async fn process_offline_queue() -> Result<(), String> {
    Ok(())
}
fn get_conflict_resolution_strategy() -> ConflictResolution {
    ConflictResolution::ClientWins
}
fn merge_states<T>(_local: &T, _server: &T) -> T
where
    T: Clone,
{
    _local.clone()
}
async fn connect_to_collaboration_service() -> Result<CollaborationStream, String> {
    Ok(CollaborationStream)
}

#[derive(Clone, Debug, Default)]
struct ThemeState;
impl ThemeState {
    fn current(&self) -> String {
        "light".to_string()
    }
    fn set(&self, _theme: &str) {}
    fn is_persisted(&self) -> bool {
        true
    }
    fn system_preference(&self) -> String {
        "light".to_string()
    }
}

#[derive(Clone, Debug, Default)]
struct LanguageState;

#[derive(Clone, Debug, Default)]
struct AuthState;

#[derive(Clone, Debug, Default)]
struct PageState<T>(std::marker::PhantomData<T>);

impl DashboardPageState {
    fn filters(&self) -> HashMap<String, serde_json::Value> {
        self.filters.clone()
    }
    fn sort_order(&self) -> String {
        self.sort_order.clone()
    }
    fn set_date_range(&self, _range: String) {}
    fn set_sort_order(&self, _order: String) {}
    fn is_dirty(&self) -> bool {
        false
    }
}

#[derive(Clone, Debug)]
struct Metric;

#[derive(Clone, Debug)]
struct UserPreferences;

struct CollaborationStream;

impl CollaborationStream {
    async fn next(&mut self) -> Option<CollaborationUpdate> {
        None
    }
}
