(function () {
  const LOG = "[WespKioskPairing]";
  const API = {
    status: "/api/kiosk/status",
    accessLink: "/api/kiosk/access-link",
    setupAvailable: "/api/kiosk/setup-available",
  };
  const LOCALHOST_HOSTS = new Set(["localhost", "127.0.0.1", "::1"]);

  function isLocalhostContext() {
    return LOCALHOST_HOSTS.has((window.location.hostname || "").toLowerCase());
  }

  function ensureModalStyles() {
    const criticalId = "wespKioskPairCriticalCss";
    if (!document.getElementById(criticalId)) {
      const style = document.createElement("style");
      style.id = criticalId;
      style.textContent =
        "#kioskPairModal{display:none;position:fixed;inset:0;z-index:5000;padding:8px;background:rgba(0,0,0,.55);overflow:hidden}" +
        "#kioskPairModal.kiosk-pair-open{display:flex;align-items:stretch;justify-content:center;height:100vh;height:100dvh}" +
        "body.kiosk-pair-modal-open{overflow:hidden!important}" +
        "#kioskPairModal .kiosk-pair-panel{display:flex;flex-direction:column;width:min(480px,100%);height:100%;max-height:100%;min-height:0;overflow:hidden;box-sizing:border-box}" +
        "#kioskPairModal .kiosk-pair-body{flex:1 1 auto;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch}" +
        "#kioskPairModal .kiosk-pair-actions{flex:0 0 auto;display:flex;flex-wrap:wrap;gap:6px}";
      document.head.appendChild(style);
    }
    if (document.getElementById("wespKioskModalsCss")) return;
    if (window.WespKioskTheme && typeof window.WespKioskTheme.ensureModalStyles === "function") {
      window.WespKioskTheme.ensureModalStyles();
      return;
    }
    const link = document.createElement("link");
    link.id = "wespKioskModalsCss";
    link.rel = "stylesheet";
    link.href = "/static/css/kiosk-modals.css";
    document.head.appendChild(link);
  }

  function createModal() {
    ensureModalStyles();
    const modal = document.createElement("div");
    modal.id = "kioskPairModal";
    modal.innerHTML = `
      <div class="kiosk-pair-panel" role="dialog" aria-modal="true" aria-labelledby="kioskPairTitle">
        <div class="kiosk-pair-header">
          <h3 id="kioskPairTitle">Привязать терминал</h3>
          <p class="kiosk-pair-subtitle">Start URL для Fully Kiosk Browser</p>
        </div>
        <div class="kiosk-pair-body">
          <div class="kiosk-pair-steps">
            1) Скопируйте ссылку или отсканируйте QR.<br/>
            2) Fully Kiosk → Settings → Start URL → вставьте ссылку → Save.<br/>
            3) Перезапустите Fully Kiosk.
          </div>
          <div id="kioskPairLoading" class="kiosk-pair-loading">
            <span class="kiosk-pair-spinner"></span>
            <span>Загрузка ссылки...</span>
          </div>
          <div class="kiosk-pair-qr-wrap">
            <img id="kioskPairQr" class="kiosk-pair-qr" alt="QR Start URL" />
          </div>
          <p id="kioskPairUrl" class="kiosk-pair-url"></p>
          <p id="kioskPairStatus" class="kiosk-pair-status"></p>
        </div>
        <div class="kiosk-pair-actions">
          <button id="kioskPairCopy" type="button" class="kiosk-pair-btn kiosk-pair-btn--primary">Скопировать ссылку</button>
          <button id="kioskPairRefresh" type="button" class="kiosk-pair-btn kiosk-pair-btn--secondary">Обновить ссылку</button>
          <button id="kioskPairClose" type="button" class="kiosk-pair-btn kiosk-pair-btn--ghost">Закрыть</button>
        </div>
      </div>
    `;
    document.body.appendChild(modal);
    return modal;
  }

  function createBlockOverlay() {
    const el = document.createElement("div");
    el.id = "kioskBlockedOverlay";
    el.style.cssText =
      "display:none;position:fixed;inset:0;background:rgba(10,10,10,.78);z-index:4500;color:#fff;align-items:center;justify-content:center;text-align:center;padding:20px;";
    el.innerHTML = `
      <div style="max-width:520px">
        <h2 style="margin:0 0 10px 0">Терминал не привязан</h2>
        <p style="margin:0;line-height:1.4">Обратитесь к администратору для настройки терминала.</p>
      </div>
    `;
    document.body.appendChild(el);
    return el;
  }

  async function fetchJson(url, options) {
    const response = await fetch(url, options);
    const data = await response.json().catch(() => ({}));
    if (!response.ok) {
      console.warn(LOG, url, response.status, data.message || data);
      throw new Error(data.message || `HTTP ${response.status}`);
    }
    return data;
  }

  function setup(opts) {
    const options = opts || {};
    const modal = createModal();
    const block = createBlockOverlay();
    const qrImg = modal.querySelector("#kioskPairQr");
    const qrWrap = modal.querySelector(".kiosk-pair-qr-wrap");
    const loadingEl = modal.querySelector("#kioskPairLoading");
    const urlEl = modal.querySelector("#kioskPairUrl");
    const statusEl = modal.querySelector("#kioskPairStatus");
    const copyBtn = modal.querySelector("#kioskPairCopy");
    const refreshBtn = modal.querySelector("#kioskPairRefresh");
    const closeBtn = modal.querySelector("#kioskPairClose");
    let currentStartUrl = "";
    let canIssueAccessLink = isLocalhostContext();

    function isEnforcePairedOnly(data) {
      if (!data || typeof data !== "object") return true;
      return data.enforce_paired_only !== false;
    }

    async function refreshSetupAvailability() {
      if (isLocalhostContext()) {
        canIssueAccessLink = true;
        return true;
      }
      try {
        const data = await fetchJson(API.setupAvailable);
        canIssueAccessLink = !!data.can_issue_access_link;
      } catch (e) {
        console.warn(LOG, "setup-available error", e);
        canIssueAccessLink = false;
      }
      if (options.menuLinkSelector) {
        const menuLink = document.querySelector(options.menuLinkSelector);
        if (menuLink) {
          menuLink.style.display = canIssueAccessLink ? "" : "none";
        }
      }
      return canIssueAccessLink;
    }

    async function checkStatus() {
      if (isLocalhostContext()) {
        block.style.display = "none";
        if (typeof options.onPaired === "function") options.onPaired({ paired: true, localhost: true });
        return true;
      }
      try {
        const data = await fetchJson(API.status);
        const enforce = isEnforcePairedOnly(data);
        const paired = !!data.paired || !enforce;
        console.debug(LOG, "/api/kiosk/status", {
          paired: !!data.paired,
          enforce_paired_only: enforce,
          device_id: data.device_id,
          status: data.status,
        });
        block.style.display = paired ? "none" : "flex";
        if (paired && typeof options.onPaired === "function") options.onPaired(data);
        if (!paired && typeof options.onUnpaired === "function") options.onUnpaired(data);
        return paired;
      } catch (e) {
        console.warn(LOG, "checkStatus error", e);
        block.style.display = "flex";
        if (typeof options.onUnpaired === "function") options.onUnpaired({});
        return false;
      }
    }

    async function loadAccessLink(refresh) {
      if (!canIssueAccessLink) {
        statusEl.textContent = "Выдача Start URL доступна только администратору или с localhost.";
        statusEl.style.color = "#ff9f9f";
        return;
      }
      loadingEl.style.display = "flex";
      qrWrap.classList.remove("kiosk-pair-qr-visible");
      qrImg.removeAttribute("src");
      statusEl.textContent = refresh ? "Обновление ссылки..." : "Загрузка ссылки...";
      try {
        const data = await fetchJson(API.accessLink, {
          method: refresh ? "POST" : "GET",
          headers: refresh ? { "Content-Type": "application/json" } : undefined,
          body: refresh ? JSON.stringify({ refresh: true }) : undefined,
        });
        currentStartUrl = data.start_url || data.pair_url || "";
        console.info(LOG, "access-link OK", { start_url: currentStartUrl.slice(0, 80) });
        const qrSrc = data.qr_image_url || "";
        await new Promise((resolve) => {
          const done = () => {
            qrImg.onload = null;
            qrImg.onerror = null;
            resolve();
          };
          qrImg.onload = done;
          qrImg.onerror = done;
          qrImg.src = qrSrc;
        });
        loadingEl.style.display = "none";
        qrWrap.classList.add("kiosk-pair-qr-visible");
        qrImg.style.display = "block";
        urlEl.textContent = currentStartUrl;
        statusEl.textContent = "Постоянная ссылка. Вставьте её в Fully Kiosk → Start URL.";
        statusEl.style.color = "";
      } catch (e) {
        loadingEl.style.display = "none";
        statusEl.textContent = globalThis.WespUserMessages?.userFacingMessage?.(e.message, "Не удалось получить ссылку") || "Не удалось получить ссылку";
        statusEl.style.color = "#ff9f9f";
      }
    }

    async function openModal() {
      if (!canIssueAccessLink) {
        window.alert("Выдача Start URL доступна только администратору или при открытии с localhost.");
        return;
      }
      modal.classList.add("kiosk-pair-open");
      document.body.classList.add("kiosk-pair-modal-open");
      loadAccessLink(false);
    }

    function closeModal() {
      modal.classList.remove("kiosk-pair-open");
      document.body.classList.remove("kiosk-pair-modal-open");
    }

    async function copyStartUrl() {
      if (!currentStartUrl) {
        statusEl.textContent = "Сначала дождитесь загрузки ссылки";
        return;
      }
      try {
        if (navigator.clipboard && navigator.clipboard.writeText) {
          await navigator.clipboard.writeText(currentStartUrl);
        } else {
          const ta = document.createElement("textarea");
          ta.value = currentStartUrl;
          ta.style.position = "fixed";
          ta.style.left = "-9999px";
          document.body.appendChild(ta);
          ta.select();
          document.execCommand("copy");
          document.body.removeChild(ta);
        }
        statusEl.textContent = "Ссылка скопирована";
        statusEl.style.color = "#9fd89f";
      } catch (e) {
        statusEl.textContent = "Не удалось скопировать — выделите ссылку вручную";
        statusEl.style.color = "#ff9f9f";
      }
    }

    async function refreshLink() {
      if (!window.confirm("Старая ссылка перестанет работать. Обновить Start URL?")) {
        return;
      }
      await loadAccessLink(true);
    }

    copyBtn.addEventListener("click", copyStartUrl);
    refreshBtn.addEventListener("click", refreshLink);
    closeBtn.addEventListener("click", closeModal);
    modal.addEventListener("click", (e) => {
      if (e.target === modal) closeModal();
    });

    if (options.menuLinkSelector) {
      const menuLink = document.querySelector(options.menuLinkSelector);
      if (menuLink) {
        menuLink.addEventListener("click", (e) => {
          e.preventDefault();
          openModal();
        });
      }
    }

    refreshSetupAvailability().then(function () {
      checkStatus();
    });
    return { checkStatus, openModal };
  }

  window.WespKioskPairing = { setup };
})();
