let razorpayLoader;
const projectCheckoutLocks = new Map();
function loadRazorpayCheckout() {
    if (typeof window.Razorpay === 'function')
        return Promise.resolve(window.Razorpay);
    if (razorpayLoader)
        return razorpayLoader;
    razorpayLoader = new Promise((resolve, reject) => {
        const script = document.createElement('script');
        script.src = 'https://checkout.razorpay.com/v1/checkout.js';
        script.async = true;
        const timer = setTimeout(() => fail(), 20000);
        function fail() { clearTimeout(timer); script.remove(); razorpayLoader = null; reject(new Error('Payment checkout could not load. Please check your connection and try again.')); }
        script.onerror = fail;
        script.onload = () => { clearTimeout(timer); if (typeof window.Razorpay !== 'function')
            return fail(); resolve(window.Razorpay); };
        document.head.appendChild(script);
    });
    return razorpayLoader;
}
const checkoutMoney = value => new Intl.NumberFormat('en-IN', { style: 'currency', currency: 'INR', minimumFractionDigits: Number(value) % 100 ? 2 : 0 }).format(Number(value) / 100);
function validCheckoutQuote(quote) {
    return quote && quote.currency === 'INR' && ['subtotal_paise', 'discount_paise', 'amount_paise'].every(key => Number.isSafeInteger(quote[key]) && quote[key] >= 0)
        && quote.subtotal_paise - quote.discount_paise === quote.amount_paise;
}
function CheckoutReview({ projectId, templateId, initialQuote, onComplete, onCancel }) {
    const [quote, setQuote] = React.useState(initialQuote);
    const [code, setCode] = React.useState(initialQuote.promo_code || '');
    const [busy, setBusy] = React.useState('');
    const [error, setError] = React.useState('');
    const [message, setMessage] = React.useState('');
    const lock = React.useRef(false), alive = React.useRef(true), dialog = React.useRef(null);
    const appliedCode = quote?.promo_code || '';
    const dirtyCode = code.trim().toUpperCase() !== appliedCode;
    const template = TemplateCatalog.get(templateId);
    React.useEffect(() => {
        alive.current = true;
        dialog.current?.showModal();
        return () => { alive.current = false; dialog.current?.close(); };
    }, []);
    async function refreshQuote(promoCode) {
        if (lock.current)
            return;
        lock.current = true;
        setBusy('quote');
        setError('');
        setMessage('');
        try {
            const result = await window.EA.quoteOrder(projectId, promoCode);
            if (!alive.current)
                return;
            if (result.alreadyPaid === true) {
                onComplete(result);
                return;
            }
            if (!validCheckoutQuote(result.quote))
                throw new Error('The price could not be checked. Please try again.');
            setQuote(result.quote);
            setCode(result.quote.promo_code || '');
            setMessage(result.quote.promo_code ? 'Promo code applied. You save ' + checkoutMoney(result.quote.discount_paise) + '.' : 'The invitation price has been updated.');
        }
        catch (err) {
            if (alive.current)
                setError(err.message || 'This promo code could not be applied.');
        }
        finally {
            lock.current = false;
            if (alive.current)
                setBusy('');
        }
    }
    async function proceed(event) {
        event.preventDefault();
        if (lock.current || !validCheckoutQuote(quote))
            return;
        if (dirtyCode) {
            setError('Apply your promo code, or remove it, before continuing.');
            return;
        }
        lock.current = true;
        setBusy('payment');
        setError('');
        setMessage('');
        try {
            const result = await window.EA.createOrder(templateId, projectId, { promo_code: appliedCode, expected_amount_paise: quote.amount_paise });
            if (alive.current)
                onComplete(result);
        }
        catch (err) {
            if (!alive.current)
                return;
            setError(err.message || 'Checkout could not start. Please try again.');
            if (err.code === 'PRICE_CHANGED' || String(err.code || '').startsWith('PROMO_'))
                setQuote(null);
        }
        finally {
            lock.current = false;
            if (alive.current)
                setBusy('');
        }
    }
    return React.createElement("dialog", { className: "checkout-review", ref: dialog, "aria-labelledby": "checkout-review-title", "aria-describedby": "checkout-review-description", onCancel: event => { event.preventDefault(); if (!lock.current)
            onCancel(); } },
        React.createElement("header", { className: "checkout-review-header" },
            React.createElement("span", null, "Everafter"),
            React.createElement("button", { type: "button", className: "checkout-review-close", "aria-label": "Close checkout", disabled: Boolean(busy), onClick: onCancel }, "\u00D7")),
        React.createElement("div", { className: "checkout-review-body" },
            React.createElement("h1", { id: "checkout-review-title" }, "One last detail."),
            React.createElement("p", { id: "checkout-review-description" }, "Review your price before sharing your invitation."),
            React.createElement("div", { className: "checkout-review-product" },
                React.createElement("span", { className: "checkout-review-product-mark", "aria-hidden": "true" }, "E"),
                React.createElement("div", null,
                    React.createElement("h2", null, template?.name || 'Your invitation'),
                    React.createElement("p", null, "One invitation. One-time payment."))),
            React.createElement("form", { className: "checkout-promo", onSubmit: event => { event.preventDefault(); refreshQuote(code.trim()); } },
                React.createElement("label", { htmlFor: "checkout-promo-code" }, "Have a promo code?"),
                React.createElement("div", { className: "checkout-promo-input" },
                    React.createElement("input", { id: "checkout-promo-code", value: code, onChange: event => { setCode(event.target.value.toUpperCase()); setError(''); setMessage(''); }, placeholder: "Enter code", maxLength: 40, autoComplete: "off", autoCapitalize: "characters", spellCheck: "false", disabled: Boolean(busy), "aria-describedby": "checkout-promo-feedback" }),
                    React.createElement("button", { type: "submit", disabled: Boolean(busy) || !code.trim() }, busy === 'quote' ? 'Checking…' : 'Apply')),
                (code || appliedCode) && React.createElement("button", { type: "button", className: "checkout-promo-remove", disabled: Boolean(busy), onClick: () => refreshQuote('') }, "Remove code")),
            React.createElement("div", { id: "checkout-promo-feedback" },
                error && React.createElement("p", { className: "checkout-review-error", role: "alert" }, error),
                message && React.createElement("p", { className: "checkout-review-success", role: "status" }, message)),
            validCheckoutQuote(quote) ? React.createElement("dl", { className: "checkout-review-price", "aria-live": "polite" },
                React.createElement("div", null,
                    React.createElement("dt", null, "Invitation price"),
                    React.createElement("dd", null, checkoutMoney(quote.subtotal_paise))),
                quote.discount_paise > 0 && React.createElement("div", { className: "checkout-review-discount" },
                    React.createElement("dt", null,
                        "Discount ",
                        React.createElement("span", null, quote.promo_code)),
                    React.createElement("dd", null,
                        "\u2212",
                        checkoutMoney(quote.discount_paise))),
                React.createElement("div", { className: "checkout-review-total" },
                    React.createElement("dt", null, "Total to pay"),
                    React.createElement("dd", null, checkoutMoney(quote.amount_paise)))) : React.createElement("button", { type: "button", className: "checkout-refresh", disabled: Boolean(busy), onClick: () => refreshQuote(code.trim()) }, "Check price again"),
            React.createElement("form", { onSubmit: proceed },
                React.createElement("button", { className: "checkout-review-pay", type: "submit", disabled: Boolean(busy) || !validCheckoutQuote(quote) || dirtyCode },
                    busy === 'payment' ? 'Preparing checkout…' : quote?.amount_paise === 0 ? 'Unlock invitation' : 'Continue to pay' + (validCheckoutQuote(quote) ? ' ' + checkoutMoney(quote.amount_paise) : ''),
                    React.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.7", "aria-hidden": "true" },
                        React.createElement("path", { d: "M5 12h14m-6-6 6 6-6 6" })))),
            React.createElement("p", { className: "checkout-review-assurance" }, quote?.amount_paise === 0 ? 'Your promo covers the full price. No payment details needed.' : 'Secure payment with Razorpay. No subscription.'),
            React.createElement("button", { className: "checkout-review-back", type: "button", disabled: Boolean(busy), onClick: onCancel }, "Back to editing")));
}
let activeCheckoutReview = false;
function requestCheckoutOrder({ projectId, templateId, quote }) {
    if (activeCheckoutReview)
        return Promise.reject(new Error('Finish the open checkout before starting another.'));
    activeCheckoutReview = true;
    return new Promise((resolve, reject) => {
        const previousFocus = document.activeElement;
        const mount = document.createElement('div');
        mount.className = 'checkout-review-mount';
        document.body.appendChild(mount);
        const root = ReactDOM.createRoot(mount);
        const account = window.EA.currentUser()?.id;
        let finished = false;
        const finish = (fn, result) => {
            if (finished)
                return;
            finished = true;
            activeCheckoutReview = false;
            window.removeEventListener('everafter:session', changed);
            Promise.resolve().then(() => { root.unmount(); mount.remove(); if (previousFocus?.isConnected)
                previousFocus.focus(); fn(result); });
        };
        const changed = () => { if (window.EA.currentUser()?.id !== account)
            finish(reject, new Error('Your account changed. Reopen checkout to continue.')); };
        window.addEventListener('everafter:session', changed);
        root.render(React.createElement(CheckoutReview, { projectId: projectId, templateId: templateId, initialQuote: quote, onComplete: result => finish(resolve, result), onCancel: () => finish(reject, new Error('Payment cancelled. Your invitation is still saved.')) }));
    });
}
async function checkoutProject({ projectId, templateId }) {
    if (!projectId || !window.EA?.isLoggedIn())
        throw new Error('Sign in and save this invitation before paying.');
    if (projectCheckoutLocks.has(projectId))
        return projectCheckoutLocks.get(projectId);
    const account = window.EA.currentUser?.()?.id || null;
    const assertAccount = () => { if (!window.EA.isLoggedIn() || (window.EA.currentUser?.()?.id || null) !== account)
        throw new Error('Your account changed. Reopen checkout to continue.'); };
    const task = (async () => {
        const preview = await window.EA.quoteOrder(projectId);
        assertAccount();
        if (preview.alreadyPaid === true)
            return preview.project;
        if (!validCheckoutQuote(preview.quote))
            throw new Error('The price could not be checked. Please try again.');
        const result = await window.requestCheckoutOrder({ projectId, templateId, quote: preview.quote });
        assertAccount();
        if (result.alreadyPaid === true)
            return result.project;
        const orderId = result.order?.id;
        if (!orderId || !result.key_id || !result.razorpay_order_id || !Number.isSafeInteger(result.amount) || result.amount <= 0 || result.currency !== 'INR')
            throw new Error('The payment service returned an incomplete order. Please try again.');
        const Razorpay = await loadRazorpayCheckout();
        assertAccount();
        const payment = await new Promise((resolve, reject) => {
            let settled = false;
            const finish = (fn, value) => { if (!settled) {
                settled = true;
                window.removeEventListener?.('everafter:session', changed);
                fn(value);
            } };
            const changed = () => { try {
                assertAccount();
            }
            catch (error) {
                finish(reject, error);
                checkout.close();
            } };
            const checkout = new Razorpay({
                key: result.key_id, order_id: result.razorpay_order_id, amount: result.amount, currency: result.currency,
                name: 'Everafter by Makebiodata.shop', description: (TemplateCatalog.get(templateId)?.name || 'Wedding invitation') + ' · one-time invitation payment',
                handler: response => finish(resolve, response),
                modal: { ondismiss: () => finish(reject, new Error('Payment cancelled. Your invitation is still saved.')) },
                theme: { color: '#294E45' }
            });
            checkout.on('payment.failed', response => { finish(reject, new Error(response?.error?.description || 'Payment failed. Please try again.')); checkout.close(); });
            window.addEventListener?.('everafter:session', changed);
            try {
                checkout.open();
            }
            catch (error) {
                finish(reject, error);
            }
        });
        let verified;
        assertAccount();
        try {
            verified = await window.EA.verifyOrder(orderId, payment);
        }
        catch (_) {
            throw new Error('Payment confirmation could not be checked. Your invitation is saved. Check Payments or retry publishing; a confirmed payment will not be charged again.');
        }
        assertAccount();
        if (verified.entitled !== true)
            throw new Error('Payment has not been confirmed yet. Please retry publishing; you will not be asked to pay again once it is confirmed.');
        return verified.project;
    })();
    projectCheckoutLocks.set(projectId, task);
    try {
        return await task;
    }
    finally {
        projectCheckoutLocks.delete(projectId);
    }
}
Object.assign(window, { checkoutProject, requestCheckoutOrder });
