/**
 * GOA shop pay popup — public only (no merchant secrets).
 * Flow: POST templates/{id} → taler://pay/… + payto links.
 *
 * QR display matches taler-merchant-webui QR_Taler
 * (@gnu-taler/web-util QR.tsx): animated #0042B3 conic ring + qr-logo.png.
 * Uses qrcode-generator (same lib as webui) via global QRCode if present,
 * else falls back to canvas from qrcode.min.js (davidshimjs).
 */
(function () {
  var MERCHANT_HOST = "taler.hacktivism.ch";
  /* goa-shop: dedicated instance with fixed-order product templates.
   * Instance id must stay lowercase (portal/API: capitals → odd 401s). */
  var INSTANCE = String("goa-shop").toLowerCase();
  var SHOP_PAYTO =
    "payto://x-taler-bank/bank.hacktivism.ch/goa-shop?receiver-name=GOA%20Shop";
  var SHOP_PAYTO_HTTPS = "https://bank.hacktivism.ch/webui/";

  function introBase() {
    var b = document.querySelector("base");
    return b && b.href ? b.href : "/intro/";
  }

  function logoSrc() {
    /* PNG: Android often drops SVG wordmark fill inheritance (missing "taler") */
    return introBase() + "qr-logo.png";
  }

  function templateHttps(productId) {
    return (
      "https://" +
      MERCHANT_HOST +
      "/instances/" +
      INSTANCE +
      "/templates/" +
      encodeURIComponent(productId)
    );
  }

  function payTemplateUri(productId) {
    return (
      "taler://pay-template/" +
      MERCHANT_HOST +
      "/instances/" +
      INSTANCE +
      "/" +
      encodeURIComponent(productId)
    );
  }

  function ensureModal() {
    var m = document.getElementById("goa-pay-modal");
    if (m) return m;
    m = document.createElement("div");
    m.id = "goa-pay-modal";
    m.className = "goa-pay-modal";
    m.setAttribute("role", "dialog");
    m.setAttribute("aria-modal", "true");
    m.setAttribute("aria-labelledby", "goa-pay-title");
    m.hidden = true;
    m.innerHTML =
      '<div class="goa-pay-card">' +
      '  <button type="button" class="goa-pay-x" id="goa-pay-x" aria-label="Close">×</button>' +
      '  <h3 id="goa-pay-title">Pay with Taler</h3>' +
      '  <p class="goa-pay-amount" id="goa-pay-amount"></p>' +
      '  <p class="goa-pay-hint" id="goa-pay-status">Preparing payment…</p>' +
      '  <p class="goa-pay-label">Wallet payment</p>' +
      '  <p class="goa-pay-sub">Scan with the GNU Taler Wallet to pay this product</p>' +
      '  <div class="goa-pay-taler-qr" id="goa-pay-qr-pay-wrap">' +
      '    <div class="goa-pay-taler-qr__inner" id="goa-pay-qr-pay"></div>' +
      '    <img class="goa-pay-taler-qr__logo" id="goa-pay-qr-pay-logo" alt="" />' +
      "  </div>" +
      '  <a class="goa-pay-payload" id="goa-pay-qr-payload" href="#">…</a>' +
      '  <a class="goa-pay-cta" id="goa-pay-open" href="#">Open payment link →</a>' +
      '  <p class="goa-pay-line">' +
      '    <a class="goa-pay-link" id="goa-pay-uri" href="#">taler:// URI</a>' +
      '    <span class="goa-pay-sep">·</span>' +
      '    <a class="goa-pay-link" id="goa-pay-uri-https" href="#" target="_blank" rel="noopener">HTTPS</a>' +
      "  </p>" +
      '  <div class="goa-pay-settle" id="goa-pay-settle">' +
      '    <button type="button" class="goa-pay-settle-toggle" id="goa-pay-settle-toggle" aria-expanded="false" aria-controls="goa-pay-settle-body">' +
      '      <span class="goa-pay-settle-toggle-text">Settlement account (payto) · not a wallet pay QR</span>' +
      '      <span class="goa-pay-settle-chevron" aria-hidden="true">▸</span>' +
      "    </button>" +
      '    <div class="goa-pay-settle-body" id="goa-pay-settle-body" hidden>' +
      '      <p class="goa-pay-sub goa-pay-settle-note">' +
      "        This is the merchant’s bank account address (payto://). " +
      "        The exchange wires funds here after a wallet payment. " +
      "        Do not scan this to buy the product — use the wallet QR above." +
      "      </p>" +
      '      <div class="goa-pay-payto-qr" id="goa-pay-qr-payto-wrap">' +
      '        <div class="goa-pay-payto-qr__caption">Settlement only</div>' +
      '        <div class="goa-pay-payto-qr__inner" id="goa-pay-qr-payto"></div>' +
      "      </div>" +
      '      <a class="goa-pay-payload" id="goa-pay-payto-payload" href="#">…</a>' +
      '      <p class="goa-pay-line">' +
      '        <a class="goa-pay-link" id="goa-pay-payto" href="#">payto:// URI</a>' +
      '        <span class="goa-pay-sep">·</span>' +
      '        <a class="goa-pay-link" id="goa-pay-payto-https" href="#" target="_blank" rel="noopener">HTTPS</a>' +
      "      </p>" +
      "    </div>" +
      "  </div>" +
      '  <button type="button" class="goa-pay-close" id="goa-pay-close">Close</button>' +
      "</div>";
    document.body.appendChild(m);
    function close() {
      m.classList.remove("open");
      m.hidden = true;
      // collapse settlement on close
      var body = document.getElementById("goa-pay-settle-body");
      var btn = document.getElementById("goa-pay-settle-toggle");
      if (body) body.hidden = true;
      if (btn) {
        btn.setAttribute("aria-expanded", "false");
        m.classList.remove("settle-open");
      }
    }
    m.addEventListener("click", function (e) {
      if (e.target === m) close();
    });
    document.getElementById("goa-pay-x").onclick = close;
    document.getElementById("goa-pay-close").onclick = close;
    document.getElementById("goa-pay-settle-toggle").onclick = function () {
      var body = document.getElementById("goa-pay-settle-body");
      var btn = document.getElementById("goa-pay-settle-toggle");
      var open = body.hidden;
      body.hidden = !open;
      btn.setAttribute("aria-expanded", open ? "true" : "false");
      m.classList.toggle("settle-open", open);
      if (open) {
        // paint payto QR when first expanded
        renderQr(document.getElementById("goa-pay-qr-payto"), SHOP_PAYTO, 140);
        var pp = document.getElementById("goa-pay-payto-payload");
        if (pp) {
          pp.href = SHOP_PAYTO;
          pp.textContent = SHOP_PAYTO;
        }
      }
    };
    document.addEventListener("keydown", function (e) {
      if (e.key === "Escape" && m.classList.contains("open")) close();
    });
    return m;
  }

  /**
   * Render URI as a real <img> PNG (not a live canvas).
   * davidshimjs paints canvas then often hides it for an img; if the modal is
   * still display:none, layout collapses and you only see the blue ring.
   * We always encode off-DOM and inject a fixed-size image.
   */
  function renderQr(hostEl, text, size) {
    if (!hostEl) return;
    hostEl.innerHTML = "";
    size = size || 220;
    if (!text) {
      hostEl.innerHTML = '<p class="goa-pay-hint">…</p>';
      return;
    }
    if (typeof QRCode === "undefined") {
      hostEl.innerHTML =
        '<p class="goa-pay-hint err">QR library missing (qrcode.min.js)</p>';
      return;
    }
    var level =
      QRCode.CorrectLevel && QRCode.CorrectLevel.M != null
        ? QRCode.CorrectLevel.M
        : QRCode.CorrectLevel && QRCode.CorrectLevel.L != null
          ? QRCode.CorrectLevel.L
          : 1;
    var scratch = document.createElement("div");
    scratch.setAttribute("aria-hidden", "true");
    scratch.style.cssText =
      "position:fixed;left:-9999px;top:0;width:" +
      size +
      "px;height:" +
      size +
      "px;overflow:hidden;opacity:0;pointer-events:none";
    document.body.appendChild(scratch);
    var dataUrl = "";
    try {
      new QRCode(scratch, {
        text: String(text),
        width: size,
        height: size,
        colorDark: "#000000",
        colorLight: "#ffffff",
        correctLevel: level,
      });
      var canvas = scratch.querySelector("canvas");
      var libImg = scratch.querySelector("img");
      if (canvas && canvas.width > 0) {
        try {
          dataUrl = canvas.toDataURL("image/png");
        } catch (e1) {}
      }
      if (!dataUrl && libImg && libImg.src && libImg.src.indexOf("data:") === 0) {
        dataUrl = libImg.src;
      }
    } catch (err) {
      dataUrl = "";
    }
    if (scratch.parentNode) scratch.parentNode.removeChild(scratch);

    if (!dataUrl) {
      hostEl.innerHTML =
        '<p class="goa-pay-hint err">QR encode failed</p>';
      return;
    }
    var img = document.createElement("img");
    img.alt = "QR code";
    img.width = size;
    img.height = size;
    img.src = dataUrl;
    img.style.display = "block";
    img.style.width = size + "px";
    img.style.height = size + "px";
    img.style.maxWidth = "100%";
    img.style.margin = "0 auto";
    img.style.background = "#fff";
    hostEl.appendChild(img);
  }

  function setLogo(imgEl) {
    if (!imgEl) return;
    imgEl.alt = "Taler";
    imgEl.width = 100;
    imgEl.height = 50;
    imgEl.decoding = "async";
    imgEl.src = logoSrc();
    imgEl.onerror = function () {
      imgEl.src = introBase() + "qr-logo.svg";
    };
    imgEl.style.display = "";
  }

  function normalizePayUri(uri) {
    if (!uri) return "";
    return String(uri)
      .replace(/taler\.hacktivism\.ch:443/g, "taler.hacktivism.ch")
      .replace(/:443\//g, "/")
      .replace(/:443\?/g, "?");
  }

  /** Public: template → order → taler_pay_uri (no secrets). */
  function createPayUri(productId) {
    var url = templateHttps(productId);
    return fetch(url, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: "{}",
      cache: "no-store",
    })
      .then(function (r) {
        if (!r.ok) throw new Error("template POST HTTP " + r.status);
        return r.json();
      })
      .then(function (created) {
        var oid = created.order_id;
        var tok = created.token;
        if (!oid || !tok) throw new Error("no order_id/token");
        var statusUrl =
          "https://" +
          MERCHANT_HOST +
          "/instances/" +
          INSTANCE +
          "/orders/" +
          encodeURIComponent(oid) +
          "?token=" +
          encodeURIComponent(tok);
        return fetch(statusUrl, { cache: "no-store" }).then(function (r) {
          return r.text().then(function (t) {
            var pay = "";
            try {
              var d = JSON.parse(t);
              pay = d.taler_pay_uri || "";
            } catch (e) {}
            if (!pay) {
              pay =
                "taler://pay/" +
                MERCHANT_HOST +
                "/instances/" +
                INSTANCE +
                "/" +
                oid +
                "/?c=" +
                tok;
            }
            return {
              taler_pay_uri: normalizePayUri(pay),
              order_id: oid,
              token: tok,
              status_https: statusUrl.replace(
                "taler.hacktivism.ch:443",
                "taler.hacktivism.ch"
              ),
              template_https: url,
            };
          });
        });
      });
  }

  function showPay(productId, name, amount) {
    var m = ensureModal();
    if (document.body && document.body.getAttribute("data-shop-theme") === "bank") {
      m.classList.add("bank-theme");
    } else {
      m.classList.remove("bank-theme");
    }
    document.getElementById("goa-pay-title").textContent = name || productId;
    document.getElementById("goa-pay-amount").textContent = amount || "";
    var status = document.getElementById("goa-pay-status");
    status.textContent = "Preparing payment…";
    status.className = "goa-pay-hint";
    var open = document.getElementById("goa-pay-open");
    open.removeAttribute("href");
    open.classList.add("disabled");
    open.onclick = null;
    var payLink = document.getElementById("goa-pay-uri");
    payLink.removeAttribute("href");
    payLink.classList.add("disabled");
    payLink.textContent = "taler:// URI";
    document.getElementById("goa-pay-uri-https").href = templateHttps(productId);
    document.getElementById("goa-pay-uri-https").textContent = "HTTPS";
    var paytoLink = document.getElementById("goa-pay-payto");
    paytoLink.href = SHOP_PAYTO;
    paytoLink.textContent = "payto:// URI";
    document.getElementById("goa-pay-payto-https").href = SHOP_PAYTO_HTTPS;
    document.getElementById("goa-pay-payto-https").textContent = "HTTPS";

    setLogo(document.getElementById("goa-pay-qr-pay-logo"));

    // Reset settlement panel (collapsed until user expands)
    var settleBody = document.getElementById("goa-pay-settle-body");
    var settleBtn = document.getElementById("goa-pay-settle-toggle");
    if (settleBody) settleBody.hidden = true;
    if (settleBtn) settleBtn.setAttribute("aria-expanded", "false");
    m.classList.remove("settle-open");
    var paytoHost = document.getElementById("goa-pay-qr-payto");
    if (paytoHost) paytoHost.innerHTML = "";

    // Open first so layout exists, then paint wallet QR only
    m.hidden = false;
    m.classList.add("open");
    var tpl = payTemplateUri(productId);
    renderQr(
      document.getElementById("goa-pay-qr-pay"),
      tpl,
      220
    );
    var payload = document.getElementById("goa-pay-qr-payload");
    if (payload) {
      payload.href = tpl;
      payload.textContent = tpl;
    }

    createPayUri(productId)
      .then(function (info) {
        var pay = info.taler_pay_uri;
        open.href = pay;
        open.classList.remove("disabled");
        open.textContent = "Open payment link →";
        payLink.href = pay;
        payLink.classList.remove("disabled");
        payLink.textContent = "taler:// URI";
        var uh = document.getElementById("goa-pay-uri-https");
        uh.href = info.status_https || info.template_https;
        uh.textContent = "HTTPS";
        // Live unpaid taler://pay (fresh order each open)
        renderQr(document.getElementById("goa-pay-qr-pay"), pay, 220);
        if (payload) {
          payload.href = pay;
          payload.textContent = pay;
        }
        status.textContent = "Ready — scan in wallet";
      })
      .catch(function (err) {
        status.textContent =
          "Payment setup failed: " + (err && err.message ? err.message : err);
        status.className = "goa-pay-hint err";
        open.textContent = "Retry";
        open.onclick = function (e) {
          e.preventDefault();
          showPay(productId, name, amount);
        };
      });
  }

  function bind() {
    document.querySelectorAll("[data-product]").forEach(function (el) {
      el.addEventListener("click", function (e) {
        e.preventDefault();
        var id = el.getAttribute("data-product");
        var nameEl = el.querySelector(".name");
        var priceEl = el.querySelector(".price");
        showPay(
          id,
          nameEl ? nameEl.textContent.trim() : id,
          priceEl ? priceEl.textContent.trim() : ""
        );
      });
    });
  }

  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", bind);
  } else {
    bind();
  }
})();
