/* Mersal Notifications — admin shell interactions (vanilla JS). */
(function () {
  "use strict";

  function ready(fn) {
    if (document.readyState !== "loading") fn();
    else document.addEventListener("DOMContentLoaded", fn);
  }

  var prefsBound = false;

  function savePref(pref, val) {
    var cfg = window.MNOTIF_ADMIN || {};
    var body = new FormData();
    body.append("action", "mnotif_admin_pref");
    body.append("nonce", cfg.nonce || "");
    body.append("pref", pref);
    body.append("val", val);
    return fetch(cfg.ajax || "", { method: "POST", body: body, credentials: "same-origin" })
      .then(function (r) { return r.json(); });
  }

  function applyDark(app, on) {
    if (!app) return;
    app.setAttribute("data-dark", on ? "true" : "false");
    var btn = app.querySelector("[data-mnotif-pref-dark]");
    if (btn) {
      btn.setAttribute("aria-pressed", on ? "true" : "false");
      var icon = btn.querySelector(".mi");
      if (icon && window.MNOTIFicons && window.MNOTIFicons.set) {
        window.MNOTIFicons.set(icon, on ? "light_mode" : "dark_mode");
      } else if (icon) {
        icon.textContent = on ? "light_mode" : "dark_mode";
      }
    }
    if (window.MNOTIF_ADMIN) window.MNOTIF_ADMIN.dark = on;
  }

  function applyLangPill(app, lang) {
    if (!app) return;
    app.querySelectorAll("[data-mnotif-pref-lang]").forEach(function (btn) {
      btn.classList.toggle("on", btn.getAttribute("data-mnotif-pref-lang") === lang);
    });
    if (window.MNOTIF_ADMIN) window.MNOTIF_ADMIN.lang = lang;
  }

  function reloadShell() {
    var cfg = window.MNOTIF_ADMIN || {};
    var cur = document.querySelector(".mnotif-app");
    if (!cur || !cfg.shell) return Promise.resolve();
    var collapsed = cur.getAttribute("data-collapsed");
    var scrollEl = cur.querySelector(".page.scroll");
    var scrollTop = scrollEl ? scrollEl.scrollTop : 0;
    return fetch(cfg.shell, { credentials: "same-origin" })
      .then(function (r) { return r.text(); })
      .then(function (html) {
        var doc = new DOMParser().parseFromString(html, "text/html");
        var next = doc.querySelector(".mnotif-app");
        if (!next) return;
        cur.replaceWith(next);
        if (collapsed) next.setAttribute("data-collapsed", collapsed);
        var newScroll = next.querySelector(".page.scroll");
        if (newScroll) newScroll.scrollTop = scrollTop;
        if (window.MNOTIFicons && window.MNOTIFicons.swap) window.MNOTIFicons.swap(next);
        window.mnotifInitAdminShell(next);
      });
  }

  function bindPrefs() {
    if (prefsBound) return;
    prefsBound = true;
    document.addEventListener("click", function (e) {
      var app = document.querySelector(".mnotif-app");
      if (!app) return;

      var langBtn = e.target.closest("[data-mnotif-pref-lang]");
      if (langBtn) {
        e.preventDefault();
        var lang = langBtn.getAttribute("data-mnotif-pref-lang");
        if (!lang || langBtn.classList.contains("on") || langBtn.disabled) return;
        app.querySelectorAll("[data-mnotif-pref-lang]").forEach(function (b) { b.disabled = true; });
        savePref("lang", lang)
          .then(function (res) {
            if (!res || !res.success) return;
            applyLangPill(app, lang);
            app.setAttribute("dir", lang === "en" ? "ltr" : "rtl");
            return reloadShell();
          })
          .finally(function () {
            var shell = document.querySelector(".mnotif-app");
            if (shell) shell.querySelectorAll("[data-mnotif-pref-lang]").forEach(function (b) { b.disabled = false; });
          });
        return;
      }

      var darkBtn = e.target.closest("[data-mnotif-pref-dark]");
      if (darkBtn) {
        e.preventDefault();
        var on = app.getAttribute("data-dark") !== "true";
        applyDark(app, on);
        savePref("dark", on ? "1" : "0");
      }
    });
  }

  function formSnapshot(form) {
    var snap = new FormData(form);
    var pairs = [];
    snap.forEach(function (val, key) { pairs.push(key + "=" + encodeURIComponent(val)); });
    return pairs.sort().join("&");
  }

  function syncChoiceUi(app) {
    app.querySelectorAll('.opt input[type="radio"]').forEach(function (radio) {
      var opt = radio.closest(".opt");
      if (opt) opt.classList.toggle("active", radio.checked);
    });
    app.querySelectorAll('.gw-row input[type="radio"]').forEach(function (radio) {
      var row = radio.closest(".gw-row");
      if (row) row.classList.toggle("is-on", radio.checked);
    });
    app.querySelectorAll('.sec-prov input[type="radio"]').forEach(function (radio) {
      var chip = radio.closest(".sec-prov");
      if (chip) chip.classList.toggle("active", radio.checked);
    });
    app.querySelectorAll(".otp-type input").forEach(function (radio) {
      var chip = radio.closest(".otp-type");
      if (chip) chip.classList.toggle("active", radio.checked);
    });
  }

  function ensureSavebar(form) {
    var bar = form.querySelector("[data-savebar]");
    if (bar) return bar;
    var cfg = window.MNOTIF_ADMIN || {};
    var i18n = cfg.i18n || {};
    bar = document.createElement("div");
    bar.className = "savebar is-idle";
    bar.setAttribute("data-savebar", "");
    bar.hidden = true;
    bar.innerHTML =
      '<span class="help is-status" data-savebar-status hidden></span>' +
      '<div class="save-actions">' +
      '<button type="button" class="btn" data-savebar-discard>' + (i18n.discard || "Discard") + "</button>" +
      '<button type="button" class="btn primary" data-savebar-save><span class="mi sm">save</span>' + (i18n.save || "Save") + "</button>" +
      "</div>";
    form.appendChild(bar);
    if (window.MNOTIFicons && window.MNOTIFicons.swap) window.MNOTIFicons.swap(bar);
    return bar;
  }

  // The toast lives on <body>, not inside the app shell: any ancestor with a
  // transform/filter turns `position:fixed` into a containing-block-relative
  // box, which is how it ended up tucked under the WordPress menu instead of
  // centred on the viewport.
  function showSaveToast(app, text) {
    var host = document.body || app;
    if (!host) return;
    var toast = document.querySelector("body > .mnotif-save-toast");
    if (!toast) {
      toast = document.createElement("div");
      toast.className = "mnotif-save-toast";
      toast.setAttribute("role", "status");
      toast.setAttribute("aria-live", "polite");
      host.appendChild(toast);
    }
    toast.innerHTML = '<span class="mi sm">check_circle</span>' + text;
    toast.classList.add("is-visible");
    clearTimeout(toast._mnotifHide);
    toast._mnotifHide = setTimeout(function () { toast.classList.remove("is-visible"); }, 1800);
  }

  function setSavebarState(bar, state, message) {
    if (!bar) return;
    bar.classList.remove("is-idle", "is-dirty", "is-saving", "is-saved");
    if (state === "idle") {
      bar.classList.add("is-idle");
      bar.setAttribute("hidden", "");
    } else {
      bar.classList.add(state);
      bar.removeAttribute("hidden");
    }
    var status = bar.querySelector("[data-savebar-status]");
    if (status) {
      status.hidden = !message;
      status.classList.toggle("is-ok", state === "is-saved");
      status.classList.toggle("is-warn", state === "is-dirty");
      status.innerHTML = message ? '<span class="mi sm">' + (state === "is-saved" ? "check_circle" : "edit") + "</span>" + message : "";
    }
  }

  function isInstantField(el) {
    if (!el || !el.name) return false;
    if (el.type === "checkbox") return true;
    if (el.type === "radio") return true;
    if (el.tagName === "SELECT") return true;
    if (el.type === "range" || el.hasAttribute("data-otp-range-slider")) return true;
    return false;
  }

  function saveSettingsForm(form, opts) {
    opts = opts || {};
    var cfg = window.MNOTIF_ADMIN || {};
    var bar = form._mnotifSavebar || form.querySelector("[data-savebar]");
    var i18n = cfg.i18n || {};
    if (form._mnotifSaving) return Promise.resolve(false);
    form._mnotifSaving = true;
    if (bar && !opts.silent) setSavebarState(bar, "is-saving", i18n.saving || "Saving…");

    var fd = new FormData(form);
    fd.set("action", "mnotif_save_settings");
    if (!fd.get("mnotif_nonce") && cfg.saveNonce) {
      fd.set("mnotif_nonce", cfg.saveNonce);
    }

    return fetch(cfg.ajax || "", { method: "POST", body: fd, credentials: "same-origin" })
      .then(function (r) { return r.json(); })
      .then(function (res) {
        form._mnotifSaving = false;
        if (!res || !res.success) {
          if (bar && !opts.silent) setSavebarState(bar, "is-dirty", i18n.unsaved || "Unsaved changes");
          return false;
        }
        form._mnotifSnapshot = formSnapshot(form);
        if (opts.silent) {
          showSaveToast(form.closest(".mnotif-app"), i18n.saved || "Saved");
          if (bar) setSavebarState(bar, "idle");
        } else {
          if (bar) {
            setSavebarState(bar, "is-saved", i18n.saved || "Saved");
            setTimeout(function () {
              if (formSnapshot(form) === form._mnotifSnapshot) setSavebarState(bar, "idle");
            }, 2200);
          }
        }
        return true;
      })
      .catch(function () {
        form._mnotifSaving = false;
        if (bar && !opts.silent) setSavebarState(bar, "is-dirty", i18n.unsaved || "Unsaved changes");
        return false;
      });
  }

  function markDirtyForm(form) {
    if (!form) return;
    var bar = form._mnotifSavebar || ensureSavebar(form);
    form._mnotifSavebar = bar;
    if (formSnapshot(form) === form._mnotifSnapshot) {
      setSavebarState(bar, "idle");
      return;
    }
    var i18n = (window.MNOTIF_ADMIN || {}).i18n || {};
    setSavebarState(bar, "is-dirty", i18n.unsaved || "Unsaved changes");
  }

  function scheduleFormAutoSave(form) {
    clearTimeout(form._mnotifAutoTimer);
    form._mnotifAutoTimer = setTimeout(function () {
      saveSettingsForm(form, { silent: true });
    }, 350);
  }

  function ensureFormReady(form) {
    if (!form || form.dataset.mnotifAutosave === "1") return;
    form.dataset.mnotifAutosave = "1";
    var app = form.closest(".mnotif-app");
    var bar = ensureSavebar(form);
    form._mnotifSavebar = bar;
    form._mnotifSnapshot = formSnapshot(form);

    form.addEventListener("submit", function (e) {
      e.preventDefault();
      saveSettingsForm(form, { silent: false });
    });

    var saveBtn = bar.querySelector("[data-savebar-save]");
    if (saveBtn) {
      saveBtn.addEventListener("click", function () {
        saveSettingsForm(form, { silent: false });
      });
    }

    var discardBtn = bar.querySelector("[data-savebar-discard]");
    if (discardBtn) {
      discardBtn.addEventListener("click", function () {
        form.reset();
        if (app) syncChoiceUi(app);
        form._mnotifSnapshot = formSnapshot(form);
        setSavebarState(bar, "idle");
      });
    }
  }

  function bindFormAutosave() {
    if (bindFormAutosave._done) return;
    bindFormAutosave._done = true;

    function handleFieldEvent(e) {
      var t = e.target;
      if (!t || !t.name || t.name === "mnotif_nonce") return;
      var form = t.closest(".mnotif-settings-form");
      if (!form) return;
      ensureFormReady(form);
      if (isInstantField(t)) scheduleFormAutoSave(form);
      else markDirtyForm(form);
    }

    document.addEventListener("change", handleFieldEvent, true);
    document.addEventListener("input", handleFieldEvent, true);
  }

  function initFormAutosave(form) {
    ensureFormReady(form);
  }

  window.mnotifSaveSettingsForm = saveSettingsForm;

  function initAdminShell(app) {
    if (!app) return;

    app.querySelectorAll(".mnotif-settings-form").forEach(ensureFormReady);

    /* Sidebar collapse */
    var collapseBtn = app.querySelector("[data-collapse]");
    if (collapseBtn) {
      collapseBtn.addEventListener("click", function () {
        var on = app.getAttribute("data-collapsed") === "true";
        app.setAttribute("data-collapsed", on ? "false" : "true");
      });
    }

    /* Copy shortcode */
    app.querySelectorAll("[data-copy-btn]").forEach(function (btn) {
      btn.addEventListener("click", function () {
        var box = btn.closest("[data-copy]");
        var txt = box ? (box.querySelector("span") || {}).textContent : "[mersal_otp]";
        if (navigator.clipboard) navigator.clipboard.writeText(txt);
        var orig = btn.textContent;
        btn.textContent = "Copied ✓";
        setTimeout(function () { btn.textContent = orig; }, 1400);
      });
    });

    /* First-run onboarding wizard step navigation */
    (function () {
      var modal = app.querySelector("[data-mnotif-onboard]");
      if (!modal) return;
      var steps = Array.prototype.slice.call(modal.querySelectorAll(".mnotif-ob-step"));
      var bars = Array.prototype.slice.call(modal.querySelectorAll(".mnotif-ob-bar"));
      var back = modal.querySelector("[data-ob-back]");
      var next = modal.querySelector("[data-ob-next]");
      var finish = modal.querySelector("[data-ob-finish]");
      var i = 0;
      function render() {
        steps.forEach(function (s, n) { s.hidden = n !== i; });
        bars.forEach(function (b, n) { b.style.background = n <= i ? "var(--accent)" : "var(--border)"; });
        if (back) back.hidden = i === 0;
        var last = i === steps.length - 1;
        if (next) next.hidden = last;
        if (finish) finish.hidden = !last;
      }
      if (next) next.addEventListener("click", function () { if (i < steps.length - 1) { i++; render(); } });
      if (back) back.addEventListener("click", function () { if (i > 0) { i--; render(); } });
      render();
    })();

    /* Reflect chosen color next to the swatch on the Appearance page */
    var color = app.querySelector('input[type="color"][name="mnotif[btn_color]"]');
    if (color) {
      color.addEventListener("input", function () {
        var hint = color.parentNode.querySelector(".hint");
        if (hint) hint.textContent = color.value;
      });
    }

    /* Make radio option cards reflect selection immediately */
    app.querySelectorAll('.opt input[type="radio"]').forEach(function (radio) {
      radio.addEventListener("change", function () {
        var name = radio.getAttribute("name");
        app.querySelectorAll('.opt input[name="' + name + '"]').forEach(function (r) {
          var opt = r.closest(".opt");
          if (opt) opt.classList.toggle("active", r.checked);
        });
      });
    });

    /* Gateway picker rows */
    app.querySelectorAll(".gw-row input[type=\"radio\"]").forEach(function (radio) {
      radio.addEventListener("change", function () {
        var name = radio.getAttribute("name");
        app.querySelectorAll('.gw-row input[name="' + name + '"]').forEach(function (r) {
          var row = r.closest(".gw-row");
          if (row) row.classList.toggle("is-on", r.checked);
        });
      });
    });

    /* Security: captcha provider chips */
    app.querySelectorAll(".sec-prov input[type=\"radio\"]").forEach(function (radio) {
      radio.addEventListener("change", function () {
        var name = radio.getAttribute("name");
        app.querySelectorAll('.sec-prov input[name="' + name + '"]').forEach(function (r) {
          var chip = r.closest(".sec-prov");
          if (chip) chip.classList.toggle("active", r.checked);
        });
      });
    });

    /* Security: blocked country tags */
    app.querySelectorAll("[data-country-picker]").forEach(function (picker) {
      var input = picker.querySelector("[data-country-input]");
      var tags = picker.querySelector("[data-country-tags]");
      var select = picker.querySelector("[data-country-select]");
      var addBtn = picker.querySelector("[data-add-country]");
      if (!input || !tags || !select) return;

      function list() {
        return (input.value || "").split(",").map(function (s) { return s.trim().toUpperCase(); }).filter(Boolean);
      }

      function sync() {
        input.value = list().join(",");
        if (select) {
          Array.prototype.slice.call(select.options).forEach(function (opt) {
            if (!opt.value) return;
            opt.hidden = list().indexOf(opt.value.toUpperCase()) >= 0;
          });
        }
        input.dispatchEvent(new Event("change", { bubbles: true }));
      }

      function addTag(cc, label) {
        cc = (cc || "").toUpperCase();
        if (!cc || list().indexOf(cc) >= 0) return;
        var span = document.createElement("span");
        span.className = "country-tag";
        span.setAttribute("data-cc", cc);
        span.innerHTML = '<span class="cc">' + cc + "</span> " + (label || cc) +
          '<button type="button" class="country-tag-x" data-remove-country aria-label="Remove">&times;</button>';
        tags.appendChild(span);
        sync();
      }

      if (addBtn) {
        addBtn.addEventListener("click", function () {
          select.hidden = !select.hidden;
          if (!select.hidden) select.focus();
        });
      }
      select.addEventListener("change", function () {
        if (!select.value) return;
        var opt = select.options[select.selectedIndex];
        var label = opt.textContent.replace(/^[A-Z]{2}\s*—\s*/, "");
        addTag(select.value, label);
        select.value = "";
        select.hidden = true;
      });
      tags.addEventListener("click", function (e) {
        var btn = e.target.closest("[data-remove-country]");
        if (!btn) return;
        var tag = btn.closest(".country-tag");
        if (tag) tag.remove();
        sync();
      });
    });

    /* Media uploads (logo fields) */
    app.querySelectorAll("[data-media-upload]").forEach(function (btn) {
      btn.addEventListener("click", function () {
        if (!window.wp || !wp.media) return;
        var target = btn.getAttribute("data-media-target");
        if (!target) return;
        var input = app.querySelector(target);
        if (!input) return;

        var frame = wp.media({
          title: "Select image",
          button: { text: "Use this image" },
          multiple: false
        });
        frame.on("select", function () {
          var att = frame.state().get("selection").first();
          if (!att) return;
          var url = att.toJSON().url;
          input.value = url;
          var pv = input.closest(".field") ? input.closest(".field").querySelector("[data-logo-preview]") : null;
          if (pv) pv.src = url;
          input.dispatchEvent(new Event("change", { bubbles: true }));
        });
        frame.open();
      });
    });

    /* OTP code settings — sliders, type picker, live preview */
    (function () {
      var root = app.querySelector("[data-otp-settings]");
      if (!root) return;
      var lang = root.getAttribute("data-lang") === "en" ? "en" : "ar";
      var preview = root.querySelector("[data-otp-preview]");
      var caseBox = root.querySelector("[data-otp-case-toggle]");

      function activeType() {
        var r = root.querySelector('input[name="mnotif[otp_type]"]:checked');
        return r ? r.value : "numeric";
      }

      function sampleChar(type) {
        if (type === "alpha") {
          return "ABCDEFGHJKLMNPQRSTUVWXYZ"[Math.floor(Math.random() * 24)];
        }
        if (type === "alphanum") {
          return "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"[Math.floor(Math.random() * 32)];
        }
        return String(Math.floor(Math.random() * 10));
      }

      function renderPreview() {
        if (!preview) return;
        var len = parseInt(root.querySelector('[data-otp-range-value][name="mnotif[otp_length]"]')?.value || "6", 10);
        var type = activeType();
        var digits = preview.querySelectorAll("[data-otp-digit]");
        while (digits.length < len) {
          var span = document.createElement("span");
          span.className = "digit";
          span.setAttribute("data-otp-digit", "");
          preview.appendChild(span);
          digits = preview.querySelectorAll("[data-otp-digit]");
        }
        while (digits.length > len) {
          preview.lastElementChild.remove();
          digits = preview.querySelectorAll("[data-otp-digit]");
        }
        digits.forEach(function (el) {
          el.textContent = sampleChar(type);
        });
      }

      function formatOut(key, val) {
        val = parseInt(val, 10);
        if (key === "otp_length") {
          if (activeType() === "numeric") return lang === "en" ? val + " digits" : val + " أرقام";
          return lang === "en" ? val + " characters" : val + " أحرف";
        }
        if (key === "otp_expiry") return lang === "en" ? val + " min" : val + " دقائق";
        if (key === "resend_wait") return lang === "en" ? val + " sec" : val + " ثانية";
        return String(val);
      }

      function syncCaseToggle() {
        if (!caseBox) return;
        caseBox.classList.toggle("is-disabled", activeType() === "numeric");
      }

      root.querySelectorAll("[data-otp-range]").forEach(function (wrap) {
        var slider = wrap.querySelector("[data-otp-range-slider]");
        var hidden = wrap.querySelector("[data-otp-range-value]");
        var out = wrap.querySelector("[data-otp-range-out]");
        if (!slider || !hidden) return;
        var key = hidden.getAttribute("name") || "";
        key = key.replace("mnotif[", "").replace("]", "");
        function sync() {
          hidden.value = slider.value;
          if (out) out.textContent = formatOut(key, slider.value);
          if (key === "otp_length") renderPreview();
        }
        slider.addEventListener("input", sync);
        sync();
      });

      root.querySelectorAll(".otp-type input").forEach(function (radio) {
        radio.addEventListener("change", function () {
          root.querySelectorAll(".otp-type").forEach(function (chip) {
            chip.classList.toggle("active", chip.querySelector("input").checked);
          });
          syncCaseToggle();
          root.querySelectorAll("[data-otp-range]").forEach(function (wrap) {
            var hidden = wrap.querySelector("[data-otp-range-value]");
            var out = wrap.querySelector("[data-otp-range-out]");
            var slider = wrap.querySelector("[data-otp-range-slider]");
            if (!hidden || !out || !slider) return;
            var key = (hidden.getAttribute("name") || "").replace("mnotif[", "").replace("]", "");
            out.textContent = formatOut(key, slider.value);
          });
          renderPreview();
        });
      });

      syncCaseToggle();
      renderPreview();
    })();

    /* Message templates editor */
    (function () {
      var editor = app.querySelector("[data-tmpl-editor]");
      if (!editor) return;
      var defaultsEl = document.getElementById("mnotif-tmpl-defaults");
      var defaults = {};
      if (defaultsEl && defaultsEl.textContent) {
        try { defaults = JSON.parse(defaultsEl.textContent); } catch (e) { defaults = {}; }
      }
      var siteName = editor.getAttribute("data-preview-site") || "Site";
      var expiry = editor.getAttribute("data-preview-expiry") || "10";

      function activeEventPanel() {
        return editor.querySelector("[data-tmpl-event-panel]:not([hidden])");
      }

      function activeEventId() {
        var p = activeEventPanel();
        return p ? p.getAttribute("data-tmpl-event-panel") : "login";
      }

      function activeChannelId() {
        var btn = editor.querySelector(".tmpl-channel.active");
        return btn ? btn.getAttribute("data-tmpl-channel") : "whatsapp";
      }

      function activeField() {
        var panel = activeEventPanel();
        if (!panel) return null;
        var ch = activeChannelId();
        if (ch === "email") return panel.querySelector('[data-tmpl-input="email"]');
        return panel.querySelector('[data-tmpl-input="' + ch + '"]');
      }

      function applyPreview(text) {
        var bubble = editor.querySelector("[data-tmpl-preview]");
        if (!bubble) return;
        var sample = "284901";
        var out = (text || "")
          .replace(/\{\{otp\}\}/g, sample)
          .replace(/\{\{site_name\}\}/g, siteName)
          .replace(/\{\{site\}\}/g, siteName)
          .replace(/\{\{expiry\}\}/g, expiry)
          .replace(/\{\{minutes\}\}/g, expiry)
          .replace(/\{\{user_name\}\}/g, "Mo. Ashraf")
          .replace(/\{\{ip\}\}/g, "192.168.1.1");
        bubble.textContent = out || (editor.getAttribute("data-tmpl-lang") === "en"
          ? "Your message preview will appear here."
          : "ستظهر معاينة الرسالة هنا.");
      }

      function renderPreview() {
        var field = activeField();
        applyPreview(field ? field.value : "");
      }

      function showChannel(ch) {
        editor.querySelectorAll(".tmpl-channel").forEach(function (btn) {
          btn.classList.toggle("active", btn.getAttribute("data-tmpl-channel") === ch);
        });
        var panel = activeEventPanel();
        if (!panel) return;
        panel.querySelectorAll("[data-tmpl-panel]").forEach(function (p) {
          p.classList.toggle("hidden", p.getAttribute("data-tmpl-panel") !== ch);
        });
        renderPreview();
      }

      editor.querySelectorAll("[data-tmpl-channel]").forEach(function (btn) {
        btn.addEventListener("click", function () {
          showChannel(btn.getAttribute("data-tmpl-channel"));
        });
      });

      editor.querySelectorAll("[data-tmpl-var]").forEach(function (pill) {
        pill.addEventListener("click", function () {
          var token = pill.getAttribute("data-tmpl-var");
          var field = activeField();
          if (!field || !token) return;
          var start = field.selectionStart || 0;
          var end = field.selectionEnd || 0;
          var val = field.value || "";
          field.value = val.slice(0, start) + token + val.slice(end);
          field.focus();
          field.selectionStart = field.selectionEnd = start + token.length;
          renderPreview();
        });
      });

      editor.querySelectorAll(".tmpl-textarea, [data-tmpl-input]").forEach(function (el) {
        el.addEventListener("input", renderPreview);
      });

      var defBtn = app.querySelector("[data-tmpl-default]");
      if (defBtn) {
        defBtn.addEventListener("click", function () {
          var ev = activeEventId();
          var ch = activeChannelId();
          var defs = defaults[ev] || {};
          var panel = activeEventPanel();
          if (!panel || !defs) return;
          if (ch === "email") {
            var sub = panel.querySelector('[data-tmpl-input="email_subject"]');
            var body = panel.querySelector('[data-tmpl-input="email"]');
            if (sub && defs.email_subject !== undefined) sub.value = defs.email_subject;
            if (body && defs.email !== undefined) body.value = defs.email;
          } else {
            var ta = panel.querySelector('[data-tmpl-input="' + ch + '"]');
            if (ta && defs[ch] !== undefined) ta.value = defs[ch];
          }
          renderPreview();
        });
      }

      var testBtn = app.querySelector("[data-tmpl-test]");
      if (testBtn) {
        testBtn.addEventListener("click", function () {
          var field = activeField();
          applyPreview(field ? field.value : "");
          var bubble = editor.querySelector("[data-tmpl-preview]");
          if (bubble) bubble.scrollIntoView({ behavior: "smooth", block: "nearest" });
        });
      }

      showChannel(activeChannelId());
    })();
  }

  window.mnotifInitAdminShell = initAdminShell;

  /* ---- Topbar "What's new" bell dropdown ---- */
  var notifBound = false;
  function bindNotif() {
    if (notifBound) return;
    notifBound = true;

    document.addEventListener("click", function (e) {
      var toggle = e.target.closest("[data-notif-toggle]");
      var wrap = document.querySelector(".mnotif-notif");
      if (!wrap) return;
      var panel = wrap.querySelector("[data-notif-panel]");
      if (!panel) return;

      if (toggle) {
        e.preventDefault();
        var open = panel.hasAttribute("hidden");
        if (open) {
          panel.removeAttribute("hidden");
          toggle.setAttribute("aria-expanded", "true");
          // Mark seen → clear the pip.
          var cfg = window.MNOTIF_ADMIN || {};
          var pip = wrap.querySelector("[data-notif-pip]");
          if (pip) pip.setAttribute("hidden", "");
          if (cfg.notifNonce) {
            var body = new FormData();
            body.append("action", "mnotif_notif_seen");
            body.append("nonce", cfg.notifNonce);
            fetch(cfg.ajax || "", { method: "POST", body: body, credentials: "same-origin" }).catch(function () {});
          }
        } else {
          panel.setAttribute("hidden", "");
          toggle.setAttribute("aria-expanded", "false");
        }
        return;
      }

      // "Mark as read" button: clear the pip + the per-item "new" highlight,
      // and persist the seen timestamp.
      if (e.target.closest("[data-notif-readall]")) {
        e.preventDefault();
        var cfg2 = window.MNOTIF_ADMIN || {};
        var pip2 = wrap.querySelector("[data-notif-pip]");
        if (pip2) pip2.setAttribute("hidden", "");
        panel.querySelectorAll(".notif-item.is-new").forEach(function (it) {
          it.classList.remove("is-new");
        });
        if (cfg2.notifNonce) {
          var body2 = new FormData();
          body2.append("action", "mnotif_notif_seen");
          body2.append("nonce", cfg2.notifNonce);
          fetch(cfg2.ajax || "", { method: "POST", body: body2, credentials: "same-origin" }).catch(function () {});
        }
        return;
      }

      // Click outside closes the panel.
      if (!e.target.closest("[data-notif-panel]")) {
        panel.setAttribute("hidden", "");
        var t = wrap.querySelector("[data-notif-toggle]");
        if (t) t.setAttribute("aria-expanded", "false");
      }
    });
  }

  ready(function () {
    bindPrefs();
    bindFormAutosave();
    bindNotif();
    initAdminShell(document.querySelector(".mnotif-app"));
  });
})();

/* Choice cards (radio choices as cards): keep the .sel class in sync. */
document.addEventListener("change", function (e) {
  var group = e.target && e.target.closest ? e.target.closest(".mnotif-choice") : null;
  if (!group) return;
  group.querySelectorAll(".chc").forEach(function (l) {
    var i = l.querySelector("input");
    l.classList.toggle("sel", !!(i && i.checked));
  });
});
