// wallet-shop.js — BUY-ITEM click handler for the wallet's Shop applet.
//
// Flow:
//   1. User clicks a `.tt-buy-btn` inside a `.shop-tile`.
//   2. We open the global guard portal (`window.showGuard`) w. a prompt
//      naming the item + price.
//   3. On OK confirm → POST /dashboard/wallet/shop/buy {shop_item_slug} →
//      get {client_secret, purchase_id}.
//   4. Stripe.js confirmCardPayment (handles 3DS natively).
//   5. On Stripe success → POST /dashboard/wallet/shop/confirm {purchase_id}.
//   6. Reload the wallet (tokens + balances update server-side via the
//      Purchase.fulfill() chain that fires from BOTH /shop/confirm AND
//      the /stripe/webhook handler — whichever lands first, idempotent).
//
// Disabled tiles (`.btn-disabled` on the BUY btn — eg already-owned BAND)
// are a no-op: clicks don't open the guard portal.
//
// Module pattern matches the rest of the project (`Brief`, `SeaDeal`,
// `StageCard`) — exposes a singleton `WalletShop` w. a tested public
// `initWalletShop()` method.

const WalletShop = (function () {
    'use strict';

    function _getCsrf() {
        const m = document.cookie.match(/csrftoken=([^;]+)/);
        return m ? m[1] : '';
    }

    async function _doBuy(slug, btn, shopRoot) {
        const pmId = shopRoot.dataset.defaultPaymentMethodId || '';
        const pubKey = shopRoot.dataset.stripePublishableKey || '';
        if (!pmId) {
            // No saved payment method — surface a friendly message + bail.
            // (Server-side this would 402, but we'd rather not waste the
            // round trip OR confuse the user w. a stripe-side error.)
            alert('Add a payment method below first.');
            return;
        }
        const buyRes = await fetch('/dashboard/wallet/shop/buy', {
            method: 'POST',
            headers: {
                'X-CSRFToken': _getCsrf(),
                'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: 'shop_item_slug=' + encodeURIComponent(slug),
        });
        if (!buyRes.ok) {
            alert('Could not start purchase (' + buyRes.status + ').');
            return;
        }
        const { client_secret, purchase_id } = await buyRes.json();
        const stripe = window.Stripe(pubKey);
        const { error, paymentIntent } = await stripe.confirmCardPayment(
            client_secret, { payment_method: pmId },
        );
        if (error) {
            alert('Payment failed: ' + (error.message || 'unknown error'));
            return;
        }
        if (paymentIntent && paymentIntent.status === 'succeeded') {
            // Sync-confirm endpoint: belt-and-suspenders w. the webhook —
            // whichever lands first wins via Purchase.fulfill()'s idempotent
            // status guard. We always call it for the snappy UX.
            await fetch('/dashboard/wallet/shop/confirm', {
                method: 'POST',
                headers: {
                    'X-CSRFToken': _getCsrf(),
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: 'purchase_id=' + encodeURIComponent(purchase_id),
            });
            // Reload to refresh the Tokens + Balances applets w. the
            // freshly-minted tokens + writs.
            window.location.reload();
        }
    }

    function _onBuyClick(e) {
        const btn = e.target.closest('.tt-buy-btn');
        if (!btn) return;
        if (btn.classList.contains('btn-disabled')) return;
        e.preventDefault();
        e.stopPropagation();
        // The btn may be the original (inside .shop-tile) OR the portal
        // clone (sibling of .wallet-page) — `closest('.shop-tile')` only
        // works on the former. Read every datum from the btn itself + look
        // up the shop root via document.querySelector (singleton).
        const shopRoot = document.querySelector('.wallet-shop');
        if (!shopRoot) return;
        const slug = btn.dataset.shopItemSlug;
        const name = btn.dataset.itemName || slug;
        const priceCents = parseInt(btn.dataset.priceCents || '0', 10);
        // Render "$1" / "$4" / "$20.50" — trim ".00" for whole-dollar prices.
        const dollars = priceCents / 100;
        const priceStr = (dollars === Math.floor(dollars))
            ? '$' + dollars
            : '$' + dollars.toFixed(2);
        const message = 'Buy ' + name + ' for ' + priceStr + '?';
        if (typeof window.showGuard === 'function') {
            // Pin the wallet tooltip so the item card + microbtn stay
            // visible while the guard portal is open — otherwise the
            // cursor moving from the BUY btn down to the guard's OK/NVM
            // triggers the tooltip's mouseleave, leaving the guard's
            // "Buy {name} for ${price}?" prompt floating w. no referent.
            // Both callbacks (confirm + dismiss) unpin so the next
            // mouseleave (or the unpin-triggered _scheduleHide) dismisses
            // the tooltip after the user resolves the prompt.
            if (window.WalletTooltips && typeof window.WalletTooltips.pin === 'function') {
                window.WalletTooltips.pin();
            }
            window.showGuard(
                btn, message,
                function () {  // onConfirm
                    if (window.WalletTooltips && window.WalletTooltips.unpin) {
                        window.WalletTooltips.unpin();
                    }
                    _doBuy(slug, btn, shopRoot);
                },
                function () {  // onDismiss
                    if (window.WalletTooltips && window.WalletTooltips.unpin) {
                        window.WalletTooltips.unpin();
                    }
                },
            );
        }
    }

    function initWalletShop() {
        const shopRoot = document.querySelector('.wallet-shop');
        if (!shopRoot) return;
        // Wired-state is DOM-keyed (`data-shop-wired`) rather than a
        // module-scope flag so per-test fixture rebuilds re-wire cleanly.
        // Calling twice on the SAME root is still a safe no-op (idempotent).
        if (shopRoot.dataset.shopWired === '1') return;
        // Triple delegation — the BUY btn click can come from:
        //   (a) original tile (inside `.shop-tile`) — shopRoot listener
        //   (b) cloned main portal — kept for legacy / non-mini-portal pages
        //   (c) cloned mini portal (`#id_mini_tooltip_portal`) — production
        //       path post-microtooltip refactor; the BUY btn lives in
        //       `.tt-micro` which clones into the mini portal on hover.
        shopRoot.addEventListener('click', _onBuyClick);
        const portal = document.getElementById('id_tooltip_portal');
        if (portal) portal.addEventListener('click', _onBuyClick);
        const miniPortal = document.getElementById('id_mini_tooltip_portal');
        if (miniPortal) miniPortal.addEventListener('click', _onBuyClick);
        shopRoot.dataset.shopWired = '1';
    }

    return { initWalletShop: initWalletShop };
})();

document.addEventListener('DOMContentLoaded', WalletShop.initWalletShop);
