//! Notification history component with LocalStorage persistence.
//!
//! Shows last 100 notifications across sessions.

use leptos::prelude::*;
use serde::{Deserialize, Serialize};
use uuid::Uuid;

use super::chat_types::ChatMessage;
use super::modals::Modal;

const STORAGE_KEY: &str = "chattyness_notification_history";
const MAX_HISTORY_SIZE: usize = 100;

/// A stored notification entry for history.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct HistoryEntry {
    pub id: Uuid,
    pub sender_name: String,
    pub content: String,
    pub timestamp: i64,
    pub is_whisper: bool,
    /// Type of notification (e.g., "whisper", "system", "mod").
    pub notification_type: String,
}

impl HistoryEntry {
    /// Create from a whisper chat message.
    pub fn from_whisper(msg: &ChatMessage) -> Self {
        Self {
            id: Uuid::new_v4(),
            sender_name: msg.display_name.clone(),
            content: msg.content.clone(),
            timestamp: msg.timestamp,
            is_whisper: true,
            notification_type: "whisper".to_string(),
        }
    }
}

/// Load history from LocalStorage.
#[cfg(feature = "hydrate")]
pub fn load_history() -> Vec<HistoryEntry> {
    let window = match web_sys::window() {
        Some(w) => w,
        None => return Vec::new(),
    };

    let storage = match window.local_storage() {
        Ok(Some(s)) => s,
        _ => return Vec::new(),
    };

    let json = match storage.get_item(STORAGE_KEY) {
        Ok(Some(j)) => j,
        _ => return Vec::new(),
    };

    serde_json::from_str(&json).unwrap_or_default()
}

/// Save history to LocalStorage.
#[cfg(feature = "hydrate")]
pub fn save_history(history: &[HistoryEntry]) {
    let window = match web_sys::window() {
        Some(w) => w,
        None => return,
    };

    let storage = match window.local_storage() {
        Ok(Some(s)) => s,
        _ => return,
    };

    if let Ok(json) = serde_json::to_string(history) {
        let _ = storage.set_item(STORAGE_KEY, &json);
    }
}

/// Add an entry to history, maintaining max size.
#[cfg(feature = "hydrate")]
pub fn add_to_history(entry: HistoryEntry) {
    let mut history = load_history();
    history.insert(0, entry);
    if history.len() > MAX_HISTORY_SIZE {
        history.truncate(MAX_HISTORY_SIZE);
    }
    save_history(&history);
}

/// SSR stubs
#[cfg(not(feature = "hydrate"))]
pub fn load_history() -> Vec<HistoryEntry> {
    Vec::new()
}

#[cfg(not(feature = "hydrate"))]
pub fn save_history(_history: &[HistoryEntry]) {}

#[cfg(not(feature = "hydrate"))]
pub fn add_to_history(_entry: HistoryEntry) {}

/// Notification history modal component.
#[component]
pub fn NotificationHistoryModal(
    #[prop(into)] open: Signal<bool>,
    on_close: Callback<()>,
    /// Callback when user wants to reply to a message.
    on_reply: Callback<String>,
    /// Callback when user wants to see conversation context.
    on_context: Callback<String>,
) -> impl IntoView {
    // Load history when modal opens
    let history = Signal::derive(move || {
        if open.get() {
            load_history()
        } else {
            Vec::new()
        }
    });

    view! {
        <Modal
            open=open
            on_close=on_close.clone()
            title="Notification History"
            title_id="notification-history-title"
            max_width="max-w-2xl"
        >
            <div class="max-h-96 overflow-y-auto">
                <Show
                    when=move || !history.get().is_empty()
                    fallback=|| view! {
                        <p class="text-gray-400 text-center py-8">
                            "No notifications yet"
                        </p>
                    }
                >
                    <ul class="space-y-2">
                        <For
                            each=move || history.get()
                            key=|entry| entry.id
                            children={
                                let on_reply = on_reply.clone();
                                let on_context = on_context.clone();
                                let on_close = on_close.clone();
                                move |entry: HistoryEntry| {
                                    let sender_name = entry.sender_name.clone();
                                    let sender_for_reply = sender_name.clone();
                                    let sender_for_context = sender_name.clone();
                                    let on_reply = on_reply.clone();
                                    let on_context = on_context.clone();
                                    let on_close = on_close.clone();
                                    let on_close2 = on_close.clone();

                                    view! {
                                        <li class="p-3 bg-gray-700/50 rounded-lg border border-gray-600">
                                            <div class="flex items-start justify-between">
                                                <div class="flex-1">
                                                    <div class="flex items-center gap-2 mb-1">
                                                        <span class="text-purple-300 font-medium">
                                                            {sender_name}
                                                        </span>
                                                        <span class="text-xs text-gray-500">
                                                            {format_timestamp(entry.timestamp)}
                                                        </span>
                                                        <Show when=move || entry.is_whisper>
                                                            <span class="text-xs bg-purple-500/30 text-purple-300 px-1.5 py-0.5 rounded">
                                                                "whisper"
                                                            </span>
                                                        </Show>
                                                    </div>
                                                    <p class="text-gray-300 text-sm">
                                                        {entry.content.clone()}
                                                    </p>
                                                </div>
                                                <div class="flex gap-1 ml-2">
                                                    <button
                                                        class="px-2 py-1 text-xs bg-gray-600 hover:bg-gray-500 rounded text-gray-300"
                                                        title="Reply"
                                                        on:click={
                                                            let on_reply = on_reply.clone();
                                                            let sender = sender_for_reply.clone();
                                                            let on_close = on_close.clone();
                                                            move |_| {
                                                                on_reply.run(sender.clone());
                                                                on_close.run(());
                                                            }
                                                        }
                                                    >
                                                        "Reply"
                                                    </button>
                                                    <button
                                                        class="px-2 py-1 text-xs bg-gray-600 hover:bg-gray-500 rounded text-gray-300"
                                                        title="View conversation"
                                                        on:click={
                                                            let on_context = on_context.clone();
                                                            let sender = sender_for_context.clone();
                                                            let on_close = on_close2.clone();
                                                            move |_| {
                                                                on_context.run(sender.clone());
                                                                on_close.run(());
                                                            }
                                                        }
                                                    >
                                                        "Context"
                                                    </button>
                                                </div>
                                            </div>
                                        </li>
                                    }
                                }
                            }
                        />
                    </ul>
                </Show>
            </div>

            // Footer hint
            <div class="mt-4 pt-4 border-t border-gray-600 text-xs text-gray-500 text-center">
                "Press " <kbd class="px-1.5 py-0.5 bg-gray-700 rounded">"Esc"</kbd> " to close"
            </div>
        </Modal>
    }
}

/// Format a timestamp for display.
fn format_timestamp(timestamp: i64) -> String {
    #[cfg(feature = "hydrate")]
    {
        let date = js_sys::Date::new(&wasm_bindgen::JsValue::from_f64(timestamp as f64));
        let hours = date.get_hours();
        let minutes = date.get_minutes();
        format!("{:02}:{:02}", hours, minutes)
    }
    #[cfg(not(feature = "hydrate"))]
    {
        let _ = timestamp;
        String::new()
    }
}
