// shared/toast.js — non-blocking notification helper available to every
// tool via window.zddc.toast(msg, level, opts).
//
// Toasts collect in a bottom-right STACK. Error/warning toasts are STICKY —
// they stay until the user dismisses them (per-toast × or a "Clear all"
// button) so the message can be read, selected, and copied while
// troubleshooting. info/success toasts auto-dismiss. The message text is
// always selectable.
//
// Usage:
//   window.zddc.toast('Saved.', 'success');               // auto-dismiss
//   window.zddc.toast('Could not load: ' + e.message, 'error');  // sticky
//   window.zddc.toast('Note', 'info', { durationMs: 3000 });
//   window.zddc.toast('Heads up', 'info', { durationMs: 0 });    // force sticky
//
// Levels: 'info' (default) | 'success' | 'warning' | 'error'.
(function () {
    'use strict';

    if (!window.zddc) window.zddc = {};
    if (typeof window.zddc.toast === 'function') return;

    var DEFAULT_DURATION_MS = 5000;
    var FADE_MS = 300;
    // Levels that persist until the user dismisses them (troubleshooting).
    var STICKY = { error: true, warning: true };

    function container() {
        var c = document.getElementById('zddc-toasts');
        if (c) return c;
        c = document.createElement('div');
        c.id = 'zddc-toasts';
        c.className = 'zddc-toasts';
        document.body.appendChild(c);
        return c;
    }

    // Show/hide a "Clear all" control when 2+ toasts are stacked.
    function refreshClearAll(c) {
        var bar = c.querySelector('.zddc-toasts__clear');
        var count = c.querySelectorAll('.zddc-toast').length;
        if (count >= 2) {
            if (!bar) {
                bar = document.createElement('button');
                bar.type = 'button';
                bar.className = 'zddc-toasts__clear';
                bar.textContent = 'Clear all';
                bar.addEventListener('click', function () {
                    var all = c.querySelectorAll('.zddc-toast');
                    for (var i = 0; i < all.length; i++) dismiss(all[i]);
                });
                c.insertBefore(bar, c.firstChild);
            }
        } else if (bar) {
            bar.remove();
        }
    }

    function dismiss(el) {
        if (el._dismissed) return;
        el._dismissed = true;
        if (el._timer) clearTimeout(el._timer);
        el.classList.add('zddc-toast--fade');
        setTimeout(function () {
            if (el.parentNode) el.parentNode.removeChild(el);
            refreshClearAll(container());
        }, FADE_MS);
    }

    function toast(message, level, opts) {
        opts = opts || {};
        var lvl = (level === 'success' || level === 'error' ||
                   level === 'warning') ? level : 'info';
        var c = container();

        var el = document.createElement('div');
        el.className = 'zddc-toast zddc-toast--' + lvl;
        // ARIA: errors get assertive (interrupts SR queue), others polite.
        el.setAttribute('role', lvl === 'error' ? 'alert' : 'status');
        el.setAttribute('aria-live', lvl === 'error' ? 'assertive' : 'polite');

        // Selectable, copyable message text (its own element so clicking to
        // select doesn't dismiss the toast — only the × does).
        var msg = document.createElement('span');
        msg.className = 'zddc-toast__msg';
        msg.textContent = message == null ? '' : String(message);
        el.appendChild(msg);

        var close = document.createElement('button');
        close.type = 'button';
        close.className = 'zddc-toast__close';
        close.setAttribute('aria-label', 'Dismiss');
        close.textContent = '×';
        close.addEventListener('click', function () { dismiss(el); });
        el.appendChild(close);

        c.appendChild(el);

        // Sticky (error/warning, or opts.durationMs === 0) persists; otherwise
        // auto-dismiss after the (overridable) duration.
        var sticky = opts.durationMs === 0 ||
            (typeof opts.durationMs !== 'number' && STICKY[lvl]);
        if (!sticky) {
            var dur = typeof opts.durationMs === 'number'
                ? opts.durationMs : DEFAULT_DURATION_MS;
            el._timer = setTimeout(function () { dismiss(el); }, dur);
        }

        refreshClearAll(c);
        return el;
    }

    window.zddc.toast = toast;

    // Route window.alert() into the toast helper (non-blocking, ARIA-announced,
    // consistent). Native alert preserved on window.alertNative. alert() maps
    // to an error toast (sticky) since that's its usual purpose.
    if (typeof window.alert === 'function' && !window.alertNative) {
        window.alertNative = window.alert.bind(window);
        window.alert = function (msg) {
            toast(String(msg == null ? '' : msg), 'error');
        };
    }
})();
