// ═══════════════════════════════════════════════════════════════════
//  Notifications — single toast + stacked queue manager
// ═══════════════════════════════════════════════════════════════════
//
//  Two components live here:
//
//    NeonNotification (single)
//        Backwards-compatible single-toast component. Prefer
//        NeonToastQueue for new code — it manages stacking + auto-
//        dismiss + per-toast accent + a clean fade-out.
//
//    NeonToastQueue (queue manager)
//        Renders an array of [ToastEntry] stacked from the
//        bottom-right. Each entry has its own kind (info / success /
//        warning / danger), a message, and an optional caption.
//        Click X → emits `dismiss(id)` so the host removes the
//        entry from the array.
//
//  Auto-dismiss policy:
//    Slint can't run a timer that mutates a host-owned `[ToastEntry]`
//    without help. The pattern is:
//
//      1. Host (Rust) pushes a fresh entry onto its `Vec<ToastEntry>`
//         and republishes the model.
//      2. Host spawns a timer (e.g. tokio sleep) for `auto-dismiss-ms`
//         and removes the entry by id when it fires.
//
//    This component just renders + emits dismiss; the host owns
//    the lifecycle. Keeps the Slint side stateless and testable.
//
// ═══════════════════════════════════════════════════════════════════

import { Theme, AnimationPresets } from "../theme.slint";

// Re-exported to host code.
export struct ToastEntry {
    /// Stable id assigned by the host — used by `dismiss(id)`.
    /// Choose a monotonic counter so ids never recycle inside a
    /// session.
    id: int,
    /// One-line headline. Mandatory.
    message: string,
    /// Optional second line for context (e.g. error code).
    caption: string,
    /// `"info" | "success" | "warning" | "danger"`. Picks the
    /// accent bar colour and the leading glyph. Anything else
    /// falls back to `"info"`.
    kind: string,
}

// ═══════════════════════════════════════════════════════════════════
//  Single toast — kept for backwards compatibility
// ═══════════════════════════════════════════════════════════════════
export component NeonNotification {
    in property <string> message;
    in property <color> accent: Theme.neon-cyan;
    in-out property <bool> shown: false;
    callback dismissed;

    Rectangle {
        visible: root.shown;
        opacity: root.shown ? 1.0 : 0.0;
        animate opacity { duration: AnimationPresets.fade-in; }
        x: parent.width - 300px - Theme.sp-4;
        y: parent.height - 60px - Theme.sp-4;
        width: 300px;
        background: Theme.bg-elevated;
        border-radius: Theme.radius-md;
        border-width: 1px;
        border-color: Theme.border;
        Rectangle {
            width: 3px;
            background: root.accent;
            height: 100%;
            border-radius: 2px;
        }
        HorizontalLayout {
            padding-left: Theme.sp-4;
            padding-right: Theme.sp-3;
            padding-top: Theme.sp-2;
            padding-bottom: Theme.sp-2;
            spacing: Theme.sp-2;
            alignment: start;
            Text {
                text: root.message;
                font-size: Theme.font-sm;
                color: Theme.text-primary;
                horizontal-stretch: 1;
                vertical-alignment: center;
            }
            Rectangle {
                width: 20px; height: 20px;
                border-radius: Theme.radius-sm;
                background: close.has-hover ? Theme.bg-hover : transparent;
                Text { text: "×"; color: Theme.text-muted; font-size: Theme.font-base; horizontal-alignment: center; vertical-alignment: center; }
                close := TouchArea {
                    clicked => { root.shown = false; root.dismissed(); }
                    mouse-cursor: MouseCursor.pointer;
                }
            }
        }
    }
}

// ═══════════════════════════════════════════════════════════════════
//  NeonToastQueue — stacked manager
// ═══════════════════════════════════════════════════════════════════
export component NeonToastQueue inherits Rectangle {
    /// Active toasts. The host pushes fresh entries here and pops
    /// them in response to `dismiss(id)` (manual close) or after
    /// the host's own auto-dismiss timer fires.
    in property <[ToastEntry]> entries;
    /// Where in the parent the stack lives. `"bottom-right"` is
    /// the macOS / VSCode convention; `"top-right"` for "you
    /// have new mail" patterns. Other values: `"top-left"`,
    /// `"bottom-left"`.
    in property <string> position: "bottom-right";
    /// Toast width — same for every entry so the stack reads as a
    /// column.
    in property <length> toast-width: 320px;
    /// Stack gap.
    in property <length> stack-gap: 8px;
    /// Outer margin from the parent's edge.
    in property <length> edge-margin: 16px;

    callback dismiss(int);

    // Anchor coordinates — derived from `position`.
    property <bool> is-top: root.position == "top-right" || root.position == "top-left";
    property <bool> is-left: root.position == "top-left" || root.position == "bottom-left";

    // Background-less wrapper so we can position the column inside
    // a parent Rectangle without painting anything outside it.
    background: transparent;

    for entry[idx] in root.entries: toast := Rectangle {
        // Static toast height; per-entry the caption may push it
        // taller, so we use min-height + auto layout.
        min-height: 56px;
        width: root.toast-width;
        x: root.is-left
            ? root.edge-margin
            : parent.width - self.width - root.edge-margin;
        y: root.is-top
            ? root.edge-margin + (idx * (toast.min-height + root.stack-gap))
            : parent.height - self.height - root.edge-margin
                                        - (idx * (toast.min-height + root.stack-gap));
        background: Theme.bg-elevated;
        border-radius: Theme.radius-md;
        border-width: 1px;
        border-color: Theme.border;
        drop-shadow-blur: Theme.shadow-blur-md;
        drop-shadow-color: #00000088;

        // Fade-in on mount.
        opacity: 0;
        animate opacity { duration: AnimationPresets.fade-in; }
        init => { self.opacity = 1.0; }

        // Per-kind accent bar.
        property <color> accent: entry.kind == "success" ? Theme.neon-green
                                : entry.kind == "warning" ? Theme.neon-amber
                                : entry.kind == "danger"  ? Theme.neon-red
                                : Theme.neon-cyan;
        property <string> glyph: entry.kind == "success" ? "✓"
                                : entry.kind == "warning" ? "!"
                                : entry.kind == "danger"  ? "✕"
                                : "i";

        Rectangle {
            width: 4px;
            height: 100%;
            background: toast.accent;
            border-top-left-radius: Theme.radius-md;
            border-bottom-left-radius: Theme.radius-md;
        }

        HorizontalLayout {
            padding-left: Theme.sp-3;
            padding-right: Theme.sp-2;
            padding-top: Theme.sp-2;
            padding-bottom: Theme.sp-2;
            spacing: Theme.sp-3;
            alignment: start;

            Rectangle {
                width: 22px;
                height: 22px;
                border-radius: 11px;
                border-width: 1px;
                border-color: toast.accent;
                background: transparent;
                y: 0px;
                Text {
                    text: toast.glyph;
                    font-size: Theme.font-sm;
                    font-weight: 700;
                    color: toast.accent;
                    horizontal-alignment: center;
                    vertical-alignment: center;
                    width: parent.width;
                    height: parent.height;
                }
            }

            VerticalLayout {
                spacing: 2px;
                horizontal-stretch: 1;
                Text {
                    text: entry.message;
                    font-size: Theme.font-sm;
                    font-weight: 600;
                    color: Theme.text-primary;
                    wrap: word-wrap;
                }
                if (entry.caption != ""): Text {
                    text: entry.caption;
                    font-size: Theme.font-xs;
                    color: Theme.text-muted;
                    wrap: word-wrap;
                }
            }

            Rectangle {
                width: 22px;
                height: 22px;
                border-radius: Theme.radius-sm;
                background: x-touch.has-hover ? Theme.bg-hover : transparent;
                Text {
                    text: "×";
                    color: x-touch.has-hover ? toast.accent : Theme.text-muted;
                    font-size: Theme.font-base;
                    horizontal-alignment: center;
                    vertical-alignment: center;
                    width: parent.width;
                    height: parent.height;
                }
                x-touch := TouchArea {
                    clicked => { root.dismiss(entry.id); }
                    mouse-cursor: MouseCursor.pointer;
                    accessible-role: button;
                    accessible-label: "Cerrar notificación";
                }
            }
        }
    }
}
