use std::collections::VecDeque;

use serde::{Deserialize, Serialize};
use uuid::Uuid;

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum NotificationType {
    Info,
    Success,
    Warning,
    Error,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Notification {
    pub id: Uuid,
    pub title: String,
    pub message: Option<String>,
    pub notification_type: NotificationType,
    pub created_at: chrono::DateTime<chrono::Utc>,
    pub expires_at: Option<chrono::DateTime<chrono::Utc>>,
    pub dismissible: bool,
    pub actions: Vec<NotificationAction>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct NotificationAction {
    pub id: String,
    pub label: String,
    pub action: String, // Could be expanded to an enum
}

impl Notification {
    pub fn new(
        title: String,
        message: Option<String>,
        notification_type: NotificationType,
    ) -> Self {
        Self {
            id: Uuid::new_v4(),
            title,
            message,
            notification_type,
            created_at: chrono::Utc::now(),
            expires_at: None,
            dismissible: true,
            actions: Vec::new(),
        }
    }

    pub fn info(title: String, message: Option<String>) -> Self {
        Self::new(title, message, NotificationType::Info)
    }

    pub fn success(title: String, message: Option<String>) -> Self {
        Self::new(title, message, NotificationType::Success)
    }

    pub fn warning(title: String, message: Option<String>) -> Self {
        Self::new(title, message, NotificationType::Warning)
    }

    pub fn error(title: String, message: Option<String>) -> Self {
        Self::new(title, message, NotificationType::Error)
    }

    pub fn with_expires_at(mut self, expires_at: chrono::DateTime<chrono::Utc>) -> Self {
        self.expires_at = Some(expires_at);
        self
    }

    pub fn with_auto_dismiss(self, seconds: i64) -> Self {
        let expires_at = chrono::Utc::now() + chrono::Duration::seconds(seconds);
        self.with_expires_at(expires_at)
    }

    pub fn with_actions(mut self, actions: Vec<NotificationAction>) -> Self {
        self.actions = actions;
        self
    }

    pub fn non_dismissible(mut self) -> Self {
        self.dismissible = false;
        self
    }

    pub fn is_expired(&self) -> bool {
        if let Some(expires_at) = self.expires_at {
            chrono::Utc::now() > expires_at
        } else {
            false
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct NotificationState {
    pub notifications: VecDeque<Notification>,
    pub max_notifications: usize,
}

impl NotificationState {
    pub fn new(max_notifications: usize) -> Self {
        Self {
            notifications: VecDeque::new(),
            max_notifications,
        }
    }

    pub fn add_notification(&mut self, notification: Notification) {
        // Remove expired notifications first
        self.remove_expired();

        // Add new notification to the front
        self.notifications.push_front(notification);

        // Ensure we don't exceed max notifications
        while self.notifications.len() > self.max_notifications {
            self.notifications.pop_back();
        }
    }

    pub fn remove_notification(&mut self, id: Uuid) {
        self.notifications.retain(|n| n.id != id);
    }

    pub fn clear_notifications(&mut self) {
        self.notifications.clear();
    }

    pub fn remove_expired(&mut self) {
        self.notifications.retain(|n| !n.is_expired());
    }

    pub fn get_notifications(&self) -> &VecDeque<Notification> {
        &self.notifications
    }

    pub fn get_notification_count(&self) -> usize {
        self.notifications.len()
    }

    pub fn has_notifications(&self) -> bool {
        !self.notifications.is_empty()
    }
}

impl Default for NotificationState {
    fn default() -> Self {
        Self::new(50) // Default to 50 max notifications
    }
}
