/**
 * Embeddable "Buy a Gift Voucher" widget, shared by prints.html and
 * workshops.html so a voucher can be bought inline on whichever page the
 * customer is already on, rather than sending them off to a dedicated
 * voucher page. Owns its own ?voucher=success|cancelled return state (kept
 * separate from each page's own ?checkout= print-order param) and polls
 * GET /gift-vouchers/status once Stripe redirects back with a session id.
 *
 * Usage: <GiftVoucherWidget returnTo="prints" /> or returnTo="workshops" -
 * matches the POST /gift-vouchers/checkout returnTo values the Worker uses
 * to build success_url/cancel_url back to that same page.
 */

// Deliberately a uniquely-prefixed name, not PROXY_BASE - both prints.html
// and workshops.html already declare their own top-level `const PROXY_BASE`
// in their own inline script, and every <script type="text/babel"> on a
// page shares one global lexical scope, so redeclaring the same const name
// here would throw a page-breaking SyntaxError the moment this file loads.
const GIFT_VOUCHER_PROXY_BASE = "https://northernpixl-api-proxy.northernpixl.workers.dev";
const GIFT_VOUCHER_MIN_AMOUNT = 10;
const GIFT_VOUCHER_MAX_AMOUNT = 250;
const GIFT_VOUCHER_SUGGESTED_AMOUNTS = [25, 50, 100];

const formatGiftVoucherGBP = (n) => `£${Number(n).toFixed(2)}`;

// Polls GET /gift-vouchers/status until the webhook has actually created
// the voucher - it usually lands before Stripe redirects the browser back
// here, but that's not guaranteed, so the code isn't necessarily ready on
// the very first check.
const useGiftVoucherStatus = (sessionId) => {
    const [voucher, setVoucher] = React.useState(null);
    const [timedOut, setTimedOut] = React.useState(false);

    React.useEffect(() => {
        if (!sessionId) return;
        let cancelled = false;
        let attempts = 0;

        const poll = async () => {
            if (cancelled) return;
            attempts += 1;
            try {
                const res = await fetch(`${GIFT_VOUCHER_PROXY_BASE}/gift-vouchers/status?session_id=${encodeURIComponent(sessionId)}`);
                const data = await res.json();
                if (cancelled) return;
                if (data && data.success && data.ready && data.voucher) {
                    setVoucher(data.voucher);
                    return;
                }
            } catch (e) { /* keep polling - a transient network blip shouldn't give up */ }

            if (attempts >= 10) { setTimedOut(true); return; }
            setTimeout(poll, 1500);
        };
        poll();

        return () => { cancelled = true; };
    }, [sessionId]);

    return { voucher, timedOut };
};

function GiftVoucherWidget({ returnTo }) {
    const [amount, setAmount] = React.useState(50);
    const [customAmount, setCustomAmount] = React.useState('');
    const [loading, setLoading] = React.useState(false);
    const [error, setError] = React.useState(null);
    const [copied, setCopied] = React.useState(false);
    const [showBalanceCheck, setShowBalanceCheck] = React.useState(false);
    const [balanceCheckCode, setBalanceCheckCode] = React.useState('');
    const [balanceCheckLoading, setBalanceCheckLoading] = React.useState(false);
    const [balanceCheckError, setBalanceCheckError] = React.useState(null);
    const [balanceCheckResult, setBalanceCheckResult] = React.useState(null);

    // Read once on first render from the URL Stripe redirects back to
    // (?voucher=success|cancelled&session_id=..., set in the Worker's
    // POST /gift-vouchers/checkout success_url/cancel_url).
    const [params] = React.useState(() => new URLSearchParams(window.location.search));
    const voucherBanner = params.get('voucher');
    const sessionId = params.get('session_id');
    const { voucher, timedOut } = useGiftVoucherStatus(voucherBanner === 'success' ? sessionId : null);

    const effectiveAmount = customAmount !== '' ? Number(customAmount) : amount;
    const amountValid = Number.isFinite(effectiveAmount) && effectiveAmount >= GIFT_VOUCHER_MIN_AMOUNT && effectiveAmount <= GIFT_VOUCHER_MAX_AMOUNT;

    const handleBuy = async () => {
        if (!amountValid) return;
        setLoading(true);
        setError(null);
        try {
            const res = await fetch(`${GIFT_VOUCHER_PROXY_BASE}/gift-vouchers/checkout`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ amount: effectiveAmount, returnTo })
            });
            const data = await res.json();
            if (data && data.success && data.url) {
                window.location.href = data.url;
                return;
            }
            setError((data && data.error && data.error.description) || "Couldn't start checkout - please try again.");
        } catch (e) {
            setError("Couldn't reach checkout - please try again.");
        }
        setLoading(false);
    };

    const copyCode = () => {
        if (!voucher) return;
        navigator.clipboard.writeText(voucher.code).then(() => {
            setCopied(true);
            setTimeout(() => setCopied(false), 2000);
        }).catch(() => {});
    };

    const checkBalance = async () => {
        const code = balanceCheckCode.trim().toUpperCase();
        if (!code) return;
        setBalanceCheckLoading(true);
        setBalanceCheckError(null);
        setBalanceCheckResult(null);
        try {
            const res = await fetch(`${GIFT_VOUCHER_PROXY_BASE}/gift-vouchers/lookup?code=${encodeURIComponent(code)}`);
            const data = await res.json();
            if (data && data.success && data.voucher) {
                setBalanceCheckResult(data.voucher);
            } else {
                setBalanceCheckError((data && data.error && data.error.description) || "Couldn't check that code - please try again.");
            }
        } catch (e) {
            setBalanceCheckError("Couldn't reach the server - please try again.");
        }
        setBalanceCheckLoading(false);
    };

    if (voucherBanner === 'success') {
        return (
            <div className="mb-12 bg-slate-50 border border-slate-200 rounded-[2rem] p-6 md:p-10 text-center">
                <div className="w-14 h-14 rounded-full bg-emerald-50 flex items-center justify-center mx-auto mb-5">
                    <Icon name="checkCircle" size={26} className="text-emerald-600" />
                </div>
                <h2 className="text-2xl font-black tracking-tighter mb-2">Voucher purchased!</h2>

                {!voucher && !timedOut && (
                    <p className="text-sm text-slate-500">Generating your voucher code...</p>
                )}

                {!voucher && timedOut && (
                    <p className="text-sm text-slate-500 max-w-sm mx-auto">
                        Your payment went through, but your code is taking longer than usual to appear here.
                        It's safely recorded on our end - refresh this page in a minute, or
                        <a href="mailto:northernpixl@gmail.com" className="text-sky-600 font-bold"> get in touch</a> and we'll send it straight over.
                    </p>
                )}

                {voucher && (
                    <React.Fragment>
                        <p className="text-sm text-slate-500 mb-6 max-w-sm mx-auto">Save this code - use it at checkout on a print, or quote it when booking a workshop by email.</p>
                        <div className="bg-white border-2 border-dashed border-slate-300 rounded-2xl p-6 mb-4 max-w-sm mx-auto">
                            <p className="text-[11px] font-black uppercase tracking-widest text-slate-400 mb-2">Your voucher code</p>
                            <p className="text-2xl md:text-3xl font-black tracking-widest text-slate-900 mb-4">{voucher.code}</p>
                            <button onClick={copyCode} className="inline-flex items-center gap-2 bg-slate-900 text-white px-5 py-2.5 rounded-full font-black uppercase text-xs tracking-widest hover:bg-slate-800 transition-colors">
                                {copied ? 'Copied!' : 'Copy code'}
                            </button>
                        </div>
                        <p className="text-sm text-slate-500">
                            Worth {formatGiftVoucherGBP(voucher.initialAmount / 100)}, valid until {new Date(voucher.expiresAt).toLocaleDateString('en-GB', { day: 'numeric', month: 'long', year: 'numeric' })}.
                        </p>
                    </React.Fragment>
                )}
            </div>
        );
    }

    return (
        <div className="mb-12 bg-slate-50 border border-slate-200 rounded-[2rem] p-6 md:p-8">
            {voucherBanner === 'cancelled' && (
                <div className="mb-6 bg-amber-50 border border-amber-200 rounded-2xl p-4 flex items-center gap-3">
                    <Icon name="xCircle" size={18} className="text-amber-600 shrink-0" />
                    <p className="text-sm text-amber-800">Voucher checkout cancelled - nothing was charged.</p>
                </div>
            )}
            <div className="flex flex-col md:flex-row md:items-center gap-6 md:gap-10 justify-between">
                <div className="flex items-start gap-3 max-w-sm">
                    <div className="w-10 h-10 rounded-full bg-sky-50 flex items-center justify-center shrink-0">
                        <Icon name="gift" size={18} className="text-sky-500" />
                    </div>
                    <div>
                        <p className="font-black uppercase text-xs tracking-widest text-slate-900 mb-1">Gift Vouchers</p>
                        <p className="text-xs text-slate-500 leading-relaxed">
                            Give the gift of a moment, framed. Redeemable towards any print at checkout,
                            or a workshop booking by email - valid for 12 months, and any leftover balance stays on the code.
                        </p>
                    </div>
                </div>
                <div className="w-full md:w-auto md:min-w-[300px]">
                    <div className="grid grid-cols-3 gap-2 mb-3">
                        {GIFT_VOUCHER_SUGGESTED_AMOUNTS.map(a => (
                            <button
                                key={a}
                                onClick={() => { setAmount(a); setCustomAmount(''); }}
                                className={`py-2.5 rounded-xl font-black text-sm transition-colors border-2 ${
                                    customAmount === '' && amount === a
                                        ? 'bg-slate-900 text-white border-slate-900'
                                        : 'bg-white text-slate-900 border-slate-200 hover:border-slate-400'
                                }`}
                            >
                                {formatGiftVoucherGBP(a)}
                            </button>
                        ))}
                    </div>
                    <div className="flex gap-2">
                        <div className="relative flex-1">
                            <span className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400 font-bold text-sm">£</span>
                            <input
                                type="number"
                                min={GIFT_VOUCHER_MIN_AMOUNT}
                                max={GIFT_VOUCHER_MAX_AMOUNT}
                                step="1"
                                value={customAmount}
                                onChange={(e) => setCustomAmount(e.target.value)}
                                placeholder={`${GIFT_VOUCHER_MIN_AMOUNT}-${GIFT_VOUCHER_MAX_AMOUNT}`}
                                aria-label="Custom voucher amount in pounds"
                                className="w-full pl-6 pr-3 py-2.5 border border-slate-300 rounded-xl text-sm font-bold focus:outline-none focus:border-sky-500"
                            />
                        </div>
                        <button
                            onClick={handleBuy}
                            disabled={!amountValid || loading}
                            className="flex-1 bg-slate-900 text-white px-4 py-2.5 rounded-xl font-black uppercase text-[11px] tracking-widest hover:bg-slate-800 disabled:opacity-60 disabled:cursor-wait transition-colors whitespace-nowrap"
                        >
                            {loading ? 'Redirecting...' : `Buy ${amountValid ? formatGiftVoucherGBP(effectiveAmount) : ''}`}
                        </button>
                    </div>
                    {error && <p className="text-[11px] text-rose-600 mt-2">{error}</p>}
                </div>
            </div>

            <div className="mt-6 pt-5 border-t border-slate-200">
                {showBalanceCheck ? (
                    <div className="max-w-xs">
                        <label className="block text-[11px] font-black uppercase tracking-widest text-slate-400 mb-1.5">Check a voucher's balance</label>
                        <div className="flex gap-2">
                            <input
                                type="text"
                                value={balanceCheckCode}
                                onChange={(e) => setBalanceCheckCode(e.target.value.toUpperCase())}
                                placeholder="XXXX-XXXX-XXXX"
                                className="flex-1 border border-slate-300 rounded-lg px-3 py-2 text-sm font-bold tracking-widest focus:outline-none focus:border-sky-500"
                            />
                            <button
                                onClick={checkBalance}
                                disabled={balanceCheckLoading || !balanceCheckCode.trim()}
                                className="bg-slate-900 text-white px-4 py-2 rounded-lg font-black uppercase text-[11px] tracking-widest hover:bg-slate-800 disabled:opacity-60 transition-colors"
                            >
                                {balanceCheckLoading ? '...' : 'Check'}
                            </button>
                        </div>
                        {balanceCheckError && <p className="text-[11px] text-rose-600 mt-2">{balanceCheckError}</p>}
                        {balanceCheckResult && (
                            <div className="mt-3 p-3 rounded-lg bg-white border border-slate-200">
                                {balanceCheckResult.cancelled ? (
                                    <p className="text-sm font-black text-rose-600">This voucher has been cancelled and can no longer be used.</p>
                                ) : (
                                    <React.Fragment>
                                        <p className="text-sm font-black text-slate-900">{formatGiftVoucherGBP(balanceCheckResult.balance / 100)} <span className="font-normal text-slate-400">of {formatGiftVoucherGBP(balanceCheckResult.initialAmount / 100)} remaining</span></p>
                                        <p className="text-[11px] text-slate-400 mt-1">
                                            {balanceCheckResult.expired
                                                ? 'This voucher has expired.'
                                                : `Valid until ${new Date(balanceCheckResult.expiresAt).toLocaleDateString('en-GB', { day: 'numeric', month: 'long', year: 'numeric' })}.`}
                                        </p>
                                    </React.Fragment>
                                )}
                            </div>
                        )}
                    </div>
                ) : (
                    <button
                        onClick={() => setShowBalanceCheck(true)}
                        className="inline-flex items-center gap-2 text-slate-500 hover:text-slate-900 text-xs font-bold transition-colors"
                    >
                        <Icon name="search" size={14} />
                        Already have a voucher? Check your balance
                    </button>
                )}
            </div>
        </div>
    );
}
