/**
 * TamRank Toast Notification System
 */
(function ($) {
    'use strict';

    window.TamRankToast = {
        container: null,

        init: function () {
            // Maak container als die niet bestaat
            if (!this.container) {
                this.container = $('<div class="tam-toast-container"></div>');
                $('body').append(this.container);
            }
        },

        /**
         * Toon een toast notificatie
         * @param {string} title    - Titel van de toast
         * @param {string} message  - Bericht (optioneel)
         * @param {string} type     - Type: 'success', 'info', 'warning', 'error', 'xp'
         * @param {number} duration - Milliseconden voor auto-hide (0 = persistent)
         */
        show: function (title, message, type, duration, actionUrl, actionLabel) {
            this.init();

            type = type || 'success';

            var svgIcons = {
                'success': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" width="20" height="20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd"/></svg>',
                'info':    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" width="20" height="20"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z" clip-rule="evenodd"/></svg>',
                'warning': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" width="20" height="20"><path fill-rule="evenodd" d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd"/></svg>',
                'error':   '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" width="20" height="20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z" clip-rule="evenodd"/></svg>',
                'xp':      '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" width="20" height="20"><path fill-rule="evenodd" d="M10.868 2.884c-.321-.772-1.415-.772-1.736 0l-1.83 4.401-4.753.381c-.833.067-1.171 1.107-.536 1.651l3.62 3.102-1.106 4.637c-.194.813.691 1.456 1.405 1.02L10 15.591l4.069 2.485c.713.436 1.598-.207 1.404-1.02l-1.106-4.637 3.62-3.102c.635-.544.297-1.584-.536-1.65l-4.752-.382-1.83-4.4z" clip-rule="evenodd"/></svg>'
            };

            var ariaRoles = {
                'success': 'status',
                'info':    'status',
                'warning': 'alert',
                'error':   'alert',
                'xp':      'status'
            };

            // Error and warning are persistent by default (0 = no auto-dismiss)
            var defaultDurations = {
                'success': 4000,
                'info':    4000,
                'warning': 0,
                'error':   0,
                'xp':      5000
            };

            var autoDismiss = (typeof duration !== 'undefined' && duration !== null && duration > 0)
                ? duration
                : (defaultDurations[type] !== undefined ? defaultDurations[type] : 4000);

            var icon = svgIcons[type] || svgIcons['info'];
            var role = ariaRoles[type] || 'status';

            // Build toast — role set BEFORE appending to DOM (required for ARIA live regions)
            var toast = $('<div>')
                .addClass('tam-toast tam-toast-' + type)
                .attr('role', role);

            var iconSpan = $('<span>').addClass('tam-toast-icon').html(icon);
            var content = $('<div>').addClass('tam-toast-content')
                .append($('<p>').addClass('tam-toast-title').text(title));

            if (message) {
                content.append($('<p>').addClass('tam-toast-message').text(message));
            }

            // Auto-detect credits error and add buy link + force warning type
            var buyUrl = actionUrl;
            var buyLabel = actionLabel;
            var toastText = ((title || '') + ' ' + (message || '')).toLowerCase();
            if (toastText.indexOf('credits') !== -1) {
                if (!buyUrl) {
                    buyUrl = (window.tamRank && tamRank.buyCreditsUrl) || 'https://tamrank.com/account/?tab=buy-credits';
                    buyLabel = (window.tamRank && tamRank.i18n && tamRank.i18n.buy_credits) ? tamRank.i18n.buy_credits : 'Buy extra credits';
                }
                // Credits messages are always warnings, never errors
                if (type === 'error') {
                    type = 'warning';
                    toast.removeClass('tam-toast-error').addClass('tam-toast-warning');
                    iconSpan.html(svgIcons['warning']);
                    toast.attr('role', ariaRoles['warning']);
                    autoDismiss = 0;
                }
            }

            if (buyUrl && buyLabel) {
                content.append(
                    $('<a>').addClass('tam-toast-action')
                        .attr('href', buyUrl)
                        .attr('target', '_blank')
                        .text(buyLabel)
                );
            }

            var closeAriaLabel = (window.tamRank && tamRank.i18n && tamRank.i18n.close) ? tamRank.i18n.close : 'Close';
            var closeBtn = $('<button>').addClass('tam-toast-close')
                .attr('aria-label', closeAriaLabel)
                .html('&times;');
            closeBtn.on('click', function () {
                TamRankToast.hide(toast);
            });

            toast.append(iconSpan).append(content).append(closeBtn);
            this.container.append(toast);

            if (autoDismiss > 0) {
                var self = this;
                setTimeout(function () {
                    self.hide(toast);
                }, autoDismiss);
            }

            return toast;
        },

        /**
         * Verberg een toast met animatie
         */
        hide: function (toast) {
            toast.addClass('tam-toast-hiding');
            setTimeout(function () {
                toast.remove();
            }, 300);
        },

        /**
         * Shorthand: Success toast
         */
        success: function (title, message) {
            return this.show(title, message, 'success');
        },

        /**
         * Shorthand: XP toast
         */
        xp: function (title, message) {
            return this.show(title, message, 'xp', 5000);
        }
    };

})(jQuery);

// ── Central Notification Dispatcher ──────────────────────────────
// Usage: TamRank.notify('Saved!', 'success')
// Available types: 'success', 'info', 'warning', 'error'
// Default type: 'info'

window.TamRank = window.TamRank || {};

/**
 * Central notification dispatcher.
 * All JS modules should use this instead of TamRankToast directly.
 *
 * @param {string} message - The notification message.
 * @param {string} [type]  - Type: 'success', 'info', 'warning', 'error'. Default: 'info'.
 */
window.TamRank.notify = function (message, type, options) {
    type = type || 'info';
    options = options || {};
    if (window.TamRankToast) {
        window.TamRankToast.show(message, '', type, null, options.actionUrl || null, options.actionLabel || null);
    }
};

/**
 * Credits-out shortcut — shows a warning toast with a "Buy extra credits"
 * action linking to the user's account. Consolidates a repeated pattern
 * across ai-image-alt.js, tamrank-ai-meta.js, topical-authority-setup.js.
 *
 * @param {string} message - The error message to display.
 */
window.TamRank.notifyCreditsOut = function (message) {
    var i18n = (window.tamRank && window.tamRank.i18n) || {};
    var actionUrl = (window.tamRank && window.tamRank.buyCreditsUrl) || 'https://tamrank.com/account/?tab=buy-credits';
    var actionLabel = i18n.buy_credits || 'Buy extra credits';
    window.TamRank.notify(message, 'warning', { actionUrl: actionUrl, actionLabel: actionLabel });
};

// ── Branded Confirm Dialog ───────────────────────────────────────
// Promise-based replacement for window.confirm() — matches TamRank
// design system, supports danger variant, ESC/overlay-click cancel.
//
// Usage:
//   TamRank.confirm({ title, message, confirmLabel, cancelLabel, variant })
//     .then(function (ok) { if (ok) { ... } });
//
// Inline HTML usage:
//   <a href="..." data-tr-confirm="Are you sure?"
//      data-tr-confirm-title="Delete item"
//      data-tr-confirm-variant="danger">Delete</a>
// The link will not navigate until the user confirms.

(function () {
    var i18nFallback = function (key, fallback) {
        var i18n = (window.tamRank && window.tamRank.i18n) || {};
        return i18n[key] || fallback;
    };

    var iconSvg = {
        'default': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" width="22" height="22"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z" clip-rule="evenodd"/></svg>',
        'danger':  '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" width="22" height="22"><path fill-rule="evenodd" d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd"/></svg>',
        // 'caution' = we stopped something before it could do damage. Not an
        // alarm (nothing is broken) and not success (the action did not go
        // through), so deliberately neither red nor brand-green.
        'caution': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" width="22" height="22"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zM9 6a1 1 0 112 0v4a1 1 0 11-2 0V6zm1 8.5a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd"/></svg>'
    };

    // ── Generic Form Dialog ────────────────────────────────────────
    // Modal with arbitrary body content (typically a form). Confirm callback
    // may return false to keep the dialog open (validation failed) or a
    // Promise for async work. Resolves with the onConfirm return value, or
    // false when cancelled.
    //
    // Usage:
    //   TamRank.dialog({
    //     title: 'Edit Redirect',
    //     body: formEl,                  // HTML string or DOM node
    //     confirmLabel: 'Update',
    //     cancelLabel:  'Cancel',
    //     variant:      'primary',       // 'default'|'primary'|'danger'
    //     size:         'md',            // 'sm'|'md'|'lg'
    //     onConfirm: function (dialogEl) { ... },
    //     onCancel:  function () { ... }
    //   }).then(function (result) { ... });
    window.TamRank.dialog = function (opts) {
        opts = opts || {};
        var title        = opts.title        || '';
        var body         = opts.body         || '';
        var confirmLabel = opts.confirmLabel || i18nFallback('confirm', 'Confirm');
        var cancelLabel  = opts.cancelLabel  || i18nFallback('cancel', 'Cancel');
        var variant      = opts.variant      || 'primary';
        var size         = opts.size         || 'md';
        var onConfirm    = typeof opts.onConfirm === 'function' ? opts.onConfirm : null;
        var onCancel     = typeof opts.onCancel  === 'function' ? opts.onCancel  : null;

        return new Promise(function (resolve) {
            var overlay = document.createElement('div');
            overlay.className = 'tr-confirm-overlay tr-dialog-overlay';
            overlay.setAttribute('role', 'dialog');
            overlay.setAttribute('aria-modal', 'true');
            var titleId = 'tr-dialog-title-' + Date.now();
            overlay.setAttribute('aria-labelledby', titleId);

            var dialog = document.createElement('div');
            dialog.className = 'tr-confirm-dialog tr-dialog tr-dialog--' + size;

            var header = document.createElement('div');
            header.className = 'tr-dialog-header';
            var titleEl = document.createElement('h3');
            titleEl.className = 'tr-dialog-title';
            titleEl.id = titleId;
            titleEl.textContent = title;
            header.appendChild(titleEl);

            var closeBtn = document.createElement('button');
            closeBtn.type = 'button';
            closeBtn.className = 'tr-dialog-close';
            closeBtn.setAttribute('aria-label', cancelLabel);
            closeBtn.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>';
            header.appendChild(closeBtn);

            var bodyEl = document.createElement('div');
            bodyEl.className = 'tr-dialog-body';
            if (typeof body === 'string') {
                bodyEl.innerHTML = body;
            } else if (body && body.nodeType === 1) {
                bodyEl.appendChild(body);
            }

            var actions = document.createElement('div');
            actions.className = 'tr-confirm-actions tr-dialog-actions';

            var cancelBtn = document.createElement('button');
            cancelBtn.type = 'button';
            cancelBtn.className = 'tr-confirm-btn tr-confirm-btn--cancel';
            cancelBtn.textContent = cancelLabel;

            var confirmBtn = document.createElement('button');
            confirmBtn.type = 'button';
            confirmBtn.className = 'tr-confirm-btn tr-confirm-btn--confirm tr-dialog-btn--' + variant + (variant === 'danger' ? ' is-danger' : '');
            confirmBtn.textContent = confirmLabel;

            actions.appendChild(cancelBtn);
            actions.appendChild(confirmBtn);

            dialog.appendChild(header);
            dialog.appendChild(bodyEl);
            dialog.appendChild(actions);
            overlay.appendChild(dialog);
            document.body.appendChild(overlay);

            // Autofocus first focusable input/select/textarea, fallback to confirm button
            setTimeout(function () {
                var firstField = bodyEl.querySelector('input:not([type="hidden"]), select, textarea');
                (firstField || confirmBtn).focus();
            }, 20);

            var settled = false;
            function close(result) {
                if (settled) return;
                settled = true;
                overlay.classList.add('is-closing');
                document.removeEventListener('keydown', onKey, true);
                setTimeout(function () {
                    if (overlay.parentNode) overlay.parentNode.removeChild(overlay);
                    resolve(result);
                }, 120);
            }

            function doCancel() {
                if (onCancel) { try { onCancel(); } catch (e) {} }
                close(false);
            }

            function doConfirm() {
                if (!onConfirm) { close(true); return; }
                var ret;
                try { ret = onConfirm(dialog); } catch (e) { return; }
                if (ret === false) return; // validation failed — keep open
                if (ret && typeof ret.then === 'function') {
                    confirmBtn.disabled = true;
                    cancelBtn.disabled = true;
                    ret.then(function (val) {
                        if (val === false) {
                            confirmBtn.disabled = false;
                            cancelBtn.disabled = false;
                            return;
                        }
                        close(val === undefined ? true : val);
                    }, function () {
                        confirmBtn.disabled = false;
                        cancelBtn.disabled = false;
                    });
                    return;
                }
                close(ret === undefined ? true : ret);
            }

            closeBtn.addEventListener('click', doCancel);
            cancelBtn.addEventListener('click', doCancel);
            confirmBtn.addEventListener('click', doConfirm);

            // Click outside dialog = cancel
            overlay.addEventListener('click', function (e) {
                if (e.target === overlay) doCancel();
            });

            // Intercept form submit inside body so Enter triggers confirm logic
            var formInside = bodyEl.querySelector('form');
            if (formInside) {
                formInside.addEventListener('submit', function (e) {
                    e.preventDefault();
                    doConfirm();
                });
            }

            function onKey(e) {
                if (e.key === 'Escape') {
                    e.preventDefault();
                    doCancel();
                } else if (e.key === 'Tab') {
                    // Focus trap
                    var focusables = dialog.querySelectorAll('button, input:not([type="hidden"]), select, textarea, a[href]');
                    if (!focusables.length) return;
                    var first = focusables[0];
                    var last = focusables[focusables.length - 1];
                    if (e.shiftKey && document.activeElement === first) {
                        e.preventDefault();
                        last.focus();
                    } else if (!e.shiftKey && document.activeElement === last) {
                        e.preventDefault();
                        first.focus();
                    }
                }
            }
            document.addEventListener('keydown', onKey, true);
        });
    };

    window.TamRank.confirm = function (opts) {
        opts = opts || {};
        var title        = opts.title        || i18nFallback('confirm_default_title', 'Confirm');
        var message      = opts.message      || '';
        var confirmLabel = opts.confirmLabel || i18nFallback('confirm', 'Confirm');
        var cancelLabel  = opts.cancelLabel  || i18nFallback('cancel', 'Cancel');
        var variant      = (opts.variant === 'danger' || opts.variant === 'caution') ? opts.variant : 'default';
        // Optional lighter second paragraph for diagnostics ("usually a typo").
        var detail       = opts.detail       || '';
        // recommend:'cancel' flips the visual hierarchy: cancelling becomes the
        // weighted primary action and confirming drops to a quiet link. Use it
        // when declining is the answer we expect most people to want, e.g. a
        // save that was blocked because it would break the site. Default keeps
        // the classic hierarchy, so existing callers are unaffected.
        var recommend    = (opts.recommend === 'cancel') ? 'cancel' : 'confirm';

        return new Promise(function (resolve) {
            var overlay = document.createElement('div');
            overlay.className = 'tr-confirm-overlay';
            overlay.setAttribute('role', 'dialog');
            overlay.setAttribute('aria-modal', 'true');
            overlay.setAttribute('aria-labelledby', 'tr-confirm-title-' + Date.now());

            var dialog = document.createElement('div');
            dialog.className = 'tr-confirm-dialog';

            var body = document.createElement('div');
            body.className = 'tr-confirm-body';

            var iconEl = document.createElement('div');
            iconEl.className = 'tr-confirm-icon tr-confirm-icon--' + variant;
            iconEl.innerHTML = iconSvg[variant];

            var titleEl = document.createElement('h3');
            titleEl.className = 'tr-confirm-title';
            titleEl.id = overlay.getAttribute('aria-labelledby');
            titleEl.textContent = title;

            body.appendChild(iconEl);
            body.appendChild(titleEl);

            if (message || detail) {
                // Wrapper so the grid can put icon and title on one row while
                // the copy spans the full width underneath.
                var msgs = document.createElement('div');
                msgs.className = 'tr-confirm-msgs';

                // Blank lines split into paragraphs; the first one carries the
                // lead styling so the opening statement reads as the headline.
                String(message).split(/\n{2,}/).forEach(function (para, i) {
                    para = para.trim();
                    if (!para) return;
                    var p = document.createElement('p');
                    p.className = 'tr-confirm-message' + (i === 0 ? ' tr-confirm-message--lead' : '');
                    p.textContent = para;
                    msgs.appendChild(p);
                });

                if (detail) {
                    var detailEl = document.createElement('p');
                    detailEl.className = 'tr-confirm-message tr-confirm-message--detail';
                    detailEl.textContent = detail;
                    msgs.appendChild(detailEl);
                }

                body.appendChild(msgs);
            }

            var actions = document.createElement('div');
            actions.className = 'tr-confirm-actions';

            var flipped = (recommend === 'cancel');

            var cancelBtn = document.createElement('button');
            cancelBtn.type = 'button';
            cancelBtn.className = 'tr-confirm-btn ' + (flipped ? 'tr-confirm-btn--recommended' : 'tr-confirm-btn--cancel');
            cancelBtn.textContent = cancelLabel;

            var confirmBtn = document.createElement('button');
            confirmBtn.type = 'button';
            confirmBtn.className = 'tr-confirm-btn ' + (flipped
                ? 'tr-confirm-btn--quiet'
                : 'tr-confirm-btn--confirm' + (variant === 'danger' ? ' is-danger' : ''));
            confirmBtn.textContent = confirmLabel;

            if (flipped) {
                // Quiet action far left, recommended action in the corner the
                // eye and cursor land on.
                var spacer = document.createElement('span');
                spacer.className = 'tr-confirm-spacer';
                actions.appendChild(confirmBtn);
                actions.appendChild(spacer);
                actions.appendChild(cancelBtn);
            } else {
                actions.appendChild(cancelBtn);
                actions.appendChild(confirmBtn);
            }

            dialog.appendChild(body);
            dialog.appendChild(actions);
            overlay.appendChild(dialog);
            document.body.appendChild(overlay);

            // Focus follows the recommended action: cancel for destructive or
            // flipped dialogs, confirm when it is the natural next step. A
            // stray Enter should never trigger the risky option.
            setTimeout(function () {
                ((flipped || variant === 'danger') ? cancelBtn : confirmBtn).focus();
            }, 20);

            var settled = false;
            function close(result) {
                if (settled) return;
                settled = true;
                overlay.classList.add('is-closing');
                document.removeEventListener('keydown', onKey, true);
                setTimeout(function () {
                    if (overlay.parentNode) overlay.parentNode.removeChild(overlay);
                    resolve(result);
                }, 120);
            }

            cancelBtn.addEventListener('click', function () { close(false); });
            confirmBtn.addEventListener('click', function () { close(true); });

            // Click outside dialog = cancel
            overlay.addEventListener('click', function (e) {
                if (e.target === overlay) close(false);
            });

            // ESC = cancel, Enter = confirm (only if focus is in dialog)
            function onKey(e) {
                if (e.key === 'Escape') {
                    e.preventDefault();
                    close(false);
                } else if (e.key === 'Enter' && document.activeElement && dialog.contains(document.activeElement)) {
                    e.preventDefault();
                    close(document.activeElement === confirmBtn);
                }
            }
            document.addEventListener('keydown', onKey, true);
        });
    };

    // Global handler for [data-tr-confirm] attributes on links/buttons.
    // Intercepts the click, shows the branded dialog, and only fires the
    // original navigation/submission if the user confirms.
    document.addEventListener('click', function (e) {
        var el = e.target.closest('[data-tr-confirm]');
        if (!el) return;
        if (el.dataset.trConfirmed === '1') {
            // Already confirmed — let the original action proceed.
            delete el.dataset.trConfirmed;
            return;
        }
        e.preventDefault();
        e.stopPropagation();

        window.TamRank.confirm({
            title:        el.getAttribute('data-tr-confirm-title') || undefined,
            message:      el.getAttribute('data-tr-confirm') || '',
            confirmLabel: el.getAttribute('data-tr-confirm-label') || undefined,
            cancelLabel:  el.getAttribute('data-tr-confirm-cancel') || undefined,
            variant:      el.getAttribute('data-tr-confirm-variant') || 'default'
        }).then(function (ok) {
            if (!ok) return;
            el.dataset.trConfirmed = '1';
            // Re-trigger the original action.
            if (el.tagName === 'A' && el.href) {
                if (el.target === '_blank') {
                    window.open(el.href, '_blank');
                } else {
                    window.location.href = el.href;
                }
            } else if (el.tagName === 'BUTTON' || el.tagName === 'INPUT') {
                el.click();
            }
        });
    }, true);
})();
