{% comment %}
  Loyalfly — Product Multiplier Badge (manual snippet for legacy/custom themes)

  This one needs no external JS file or hardcoded URL — it's fully
  self-contained and calls the app's own App Proxy endpoint
  (/apps/loyalfly/...), which works identically on every theme regardless
  of Online Store version.

  Installation:
  1. Shopify admin → Online Store → Themes → your theme → Edit code
  2. Snippets → Add a new snippet → name it "loyalfly-product-badge"
  3. Paste this file's contents
  4. In your product template (product.liquid, or main-product.liquid /
     the section it renders), add {% render 'loyalfly-product-badge' %}
     near the price or Add to Cart button.
{% endcomment %}

{%- assign product_gid = 'gid://shopify/Product/' | append: product.id -%}
{%- assign collection_gids = '' -%}
{%- for c in product.collections -%}
  {%- assign collection_gids = collection_gids | append: 'gid://shopify/Collection/' | append: c.id -%}
  {%- unless forloop.last -%}{%- assign collection_gids = collection_gids | append: ',' -%}{%- endunless -%}
{%- endfor -%}
{%- assign is_logged_in = false -%}
{%- if customer -%}{%- assign is_logged_in = true -%}{%- endif -%}
{%- assign badge_color = "#6366f1" -%}

{%- comment -%}
  product.price is NOT the selected variant's price — Shopify resolves it to
  the first available variant regardless of what's picked (or in the URL's
  ?variant= param), which silently showed the wrong points total for any
  product with variant-level pricing. Ship every variant's price instead so
  the script can look up whichever one is actually selected, both on initial
  load and after the shopper changes the picker.
{%- endcomment -%}
{%- assign variants_json = '[' -%}
{%- for v in product.variants -%}
  {%- assign variants_json = variants_json | append: '{"id":' | append: v.id | append: ',"price":' | append: v.price | append: '}' -%}
  {%- unless forloop.last -%}{%- assign variants_json = variants_json | append: ',' -%}{%- endunless -%}
{%- endfor -%}
{%- assign variants_json = variants_json | append: ']' -%}

<div
  id="loyalfly-product-badge"
  data-shop="{{ shop.permanent_domain | escape }}"
  data-product-gid="{{ product_gid | escape }}"
  data-collection-gids="{{ collection_gids | escape }}"
  data-logged-in="{{ is_logged_in }}"
  data-product-price="{{ product.selected_or_first_available_variant.price }}"
  data-variants="{{ variants_json | escape }}"
  style="display:none;margin:12px 0;"
></div>

<script>
(function () {
  const el = document.getElementById('loyalfly-product-badge');
  if (!el) return;

  const shop = el.dataset.shop;
  const productGid = el.dataset.productGid;
  const collectionGids = el.dataset.collectionGids;
  const loggedIn = el.dataset.loggedIn === 'true';
  const fallbackPriceCents = parseInt(el.dataset.productPrice, 10) || 0;
  const badgeColor = {{ badge_color | json }};

  let variants = [];
  try { variants = JSON.parse(el.dataset.variants || '[]'); } catch (e) { variants = []; }

  function getSelectedVariantId() {
    const input = document.querySelector('form[action*="/cart/add"] [name="id"], [name="id"]');
    return input ? input.value : null;
  }

  function currentPriceCents() {
    const variantId = getSelectedVariantId();
    const match = variants.find(function (v) { return String(v.id) === String(variantId); });
    return match ? match.price : fallbackPriceCents;
  }

  // (priceCents / 100) can land a hair below the true decimal in IEEE754
  // (945 / 100 * 100 === 944.9999999999999, not 945) — nudge past that
  // representation noise before flooring, matching the backend's own
  // points calculation so the displayed estimate never undercounts by one.
  function floorPoints(value) {
    return Math.floor(value + 1e-6);
  }

  // Bold, bordered treatment — reserved for products a merchant has
  // deliberately boosted with a product/collection Earn Rule, so it reads as
  // "this one's special" rather than blending in with every other product.
  // Pairs the multiplier (grabs attention) with the actual point total
  // (concrete payoff) — at this shop's earn rate, "2×" alone doesn't let a
  // customer do that math in their head.
  function renderBadge(multiplier, isLoggedIn, points) {
    const pointsPart = points > 0 ? ` &mdash; <strong>${points.toLocaleString()} points</strong>` : '';
    if (isLoggedIn) {
      el.innerHTML = `
        <div style="
          display:inline-flex;align-items:center;gap:8px;
          background:${badgeColor}15;
          border:1px solid ${badgeColor}40;
          border-radius:8px;padding:8px 14px;
          font-size:13px;font-weight:600;color:${badgeColor};
          font-family:inherit;
        ">
          <span style="font-size:16px;">⭐</span>
          <span>You'll earn <strong>${multiplier}× points</strong>${pointsPart} on this product!</span>
        </div>`;
    } else {
      el.innerHTML = `
        <div style="
          display:inline-flex;align-items:center;gap:8px;
          background:${badgeColor}15;
          border:1px solid ${badgeColor}40;
          border-radius:8px;padding:8px 14px;
          font-size:13px;font-weight:600;color:${badgeColor};
          font-family:inherit;
        ">
          <span style="font-size:16px;">⭐</span>
          <span>Earn <strong>${multiplier}× points</strong>${pointsPart} on this product &mdash;
            <a href="/account/login" style="color:${badgeColor};text-decoration:underline;">sign in</a>
            to start earning
          </span>
        </div>`;
    }
    el.style.display = 'block';
  }

  // Plain, unboxed line — the standard earn rate on every other product.
  // Deliberately quieter than renderBadge so a real bonus still stands out.
  function renderStandardLine(points, isLoggedIn) {
    if (points <= 0) return;
    if (isLoggedIn) {
      el.innerHTML = `<span style="font-size:12px;color:#666;font-family:inherit;">You'll earn ${points.toLocaleString()} points on this purchase</span>`;
    } else {
      el.innerHTML = `<span style="font-size:12px;color:#666;font-family:inherit;">Earn ${points.toLocaleString()} points on this purchase &mdash; <a href="/account/login" style="color:${badgeColor};text-decoration:underline;">sign in</a> to start earning</span>`;
    }
    el.style.display = 'block';
  }

  // Re-renders with whichever variant is selected right now — called once the
  // multiplier/pointsPerDollar data arrives, and again every time the variant
  // picker changes, so the points total tracks the price the shopper actually sees.
  function renderForSelectedVariant(data) {
    const priceCents = currentPriceCents();
    if (data.multiplier && data.multiplier > 1) {
      const bonusPoints = data.pointsPerDollar
        ? floorPoints((priceCents / 100) * data.pointsPerDollar * data.multiplier)
        : 0;
      renderBadge(data.multiplier, loggedIn, bonusPoints);
      return;
    }
    if (data.pointsPerDollar) {
      const points = floorPoints((priceCents / 100) * data.pointsPerDollar);
      renderStandardLine(points, loggedIn);
    }
  }

  const params = new URLSearchParams({shop, productGid, collectionGids});

  fetch('/apps/loyalfly/product-multiplier?' + params)
    .then(function (res) { return res.json(); })
    .then(function (data) {
      if (!data.multiplier && !data.pointsPerDollar) return;
      renderForSelectedVariant(data);

      // Variant pickers vary a lot across themes (native <select>, radio
      // swatches, custom elements that only dispatch their own events) — a
      // delegated 'change' listener catches the common cases immediately,
      // and polling the cart form's hidden variant id as a fallback catches
      // the rest within a fraction of a second.
      document.addEventListener('change', function () { renderForSelectedVariant(data); });
      let lastVariantId = getSelectedVariantId();
      setInterval(function () {
        const id = getSelectedVariantId();
        if (id !== lastVariantId) {
          lastVariantId = id;
          renderForSelectedVariant(data);
        }
      }, 400);
    })
    .catch(function () { /* fail silently */ });
})();
</script>
