use dioxus::prelude::*;

#[derive(Clone, PartialEq)]
pub enum ToastType {
    Success,
    Error,
    Info,
}

#[derive(Clone, PartialEq)]
pub struct ToastMessage {
    pub id: usize,
    pub message: String,
    pub toast_type: ToastType,
}

#[derive(Clone, Copy)]
pub struct Toasts {
    items: Signal<Vec<ToastMessage>>,
    next_id: Signal<usize>,
}

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

impl Toasts {
    pub fn new() -> Self {
        Self {
            items: Signal::new(vec![]),
            next_id: Signal::new(0),
        }
    }

    pub fn push(&mut self, toast_type: ToastType, message: impl Into<String>) {
        let id = *self.next_id.read();
        *self.next_id.write() = id + 1;
        self.items.write().push(ToastMessage {
            id,
            message: message.into(),
            toast_type,
        });

        #[cfg(feature = "web")]
        {
            let mut items = self.items;
            spawn(async move {
                gloo_timers::future::TimeoutFuture::new(4_000).await;
                items.write().retain(|t| t.id != id);
            });
        }
    }

    pub fn remove(&mut self, id: usize) {
        self.items.write().retain(|t| t.id != id);
    }
}

#[component]
pub fn ToastContainer() -> Element {
    let mut toasts = use_context::<Toasts>();
    let items = toasts.items.read();

    rsx! {
        div { class: "toast-container",
            for toast in items.iter() {
                {
                    let toast_id = toast.id;
                    let type_class = match toast.toast_type {
                        ToastType::Success => "toast-success",
                        ToastType::Error => "toast-error",
                        ToastType::Info => "toast-info",
                    };
                    rsx! {
                        div {
                            key: "{toast_id}",
                            class: "toast {type_class}",
                            span { "{toast.message}" }
                            button {
                                class: "toast-dismiss",
                                onclick: move |_| toasts.remove(toast_id),
                                "\u{00d7}"
                            }
                        }
                    }
                }
            }
        }
    }
}
