// NOTE: intentionally `var`, not `const`/`let` - navbar.jsx (loaded just
// above this script on guides.html) already destructures these same names
// at its own top level; a second top-level `const` here for the same
// names throws a page-breaking SyntaxError the moment this script runs.
var { useState, useEffect, useCallback } = React;

const PROXY_BASE = "https://northernpixl-api-proxy.northernpixl.workers.dev";

// Every Field Guide, in the same order they're listed in workers/index.js's
// own GUIDE_CATALOG - `key` must match exactly, since it's sent straight
// through to POST /guides/checkout and back from GET /guides/status.
// localStorageKey matches each guide's own page (its 01-app.jsx reads this
// same key on load), so "Open guide" below can hand a freshly-bought code
// straight to the right page without the customer re-typing it.
const GUIDES_CATALOG = [
    {
        key: "milkyway",
        title: "Milky Way Field Guide",
        icon: "stars",
        blurb: "Camera, lens, tracker and stacking software (Siril, Sequator, DeepSkyStacker, PixInsight, Starry Landscape Stacker) - a complete astrophotography workflow, start to finish.",
        href: "field-guide.html",
        localStorageKey: "np_field_guide_code"
    },
    {
        key: "aurora",
        title: "Aurora Borealis Field Guide",
        icon: "moon",
        blurb: "Single-frame technique built around how the aurora actually moves - stacking software smears it, so this guide uses noise reduction instead.",
        href: "aurora-guide.html",
        localStorageKey: "np_aurora_guide_code"
    },
    {
        key: "waterfall",
        title: "Waterfalls Field Guide",
        icon: "waves",
        blurb: "An ND filter and shutter-speed calculator, on-site safety notes, plus its own self-contained focus-stacking and exposure-bracketing walkthroughs.",
        href: "waterfall-guide.html",
        localStorageKey: "np_waterfall_guide_code"
    },
    {
        key: "focusstack",
        title: "Focus Stacking Field Guide",
        icon: "layers",
        blurb: "Helicon Focus, Zerene Stacker, or Photoshop - tailored to macro, product, or landscape subjects, with real frame-count and step-size guidance.",
        href: "focus-stack-guide.html",
        localStorageKey: "np_focus_stack_guide_code"
    },
    {
        key: "exposurebracket",
        title: "Exposure Bracketing Field Guide",
        icon: "sunrise",
        blurb: "Bracket-size and EV-spacing guidance by scene, plus a complete merge-and-finish workflow in Photomatix, Aurora HDR, Lightroom, or Photoshop.",
        href: "exposure-bracket-guide.html",
        localStorageKey: "np_exposure_bracket_guide_code"
    }
];

const SOLO_PRICE_PENCE = 500; // £5.00 - must match each guide's own *_PRICE_PENCE in workers/index.js

// Keyed by how many DISTINCT guides are selected, not which ones - must
// match GUIDE_BUNDLE_PRICES_PENCE in workers/index.js exactly, since that's
// the actual source of truth POST /guides/checkout prices from. This
// client-side copy only drives the live "Total" display as the customer
// selects guides - never trusted for the real charge.
const BUNDLE_PRICES_PENCE = { 1: 300, 2: 500, 3: 700, 4: 900, 5: 1100 };

const formatGBP = (pence) => `£${(pence / 100).toFixed(2)}`;

function App() {
    const { user: authUser, getIdToken } = useAuth();
    const [filter, setFilter] = useState("all");
    const [selected, setSelected] = useState(() => new Set());
    const [purchaseLoading, setPurchaseLoading] = useState(false);
    const [purchaseError, setPurchaseError] = useState(null);

    // Post-purchase return: ?purchase=success&session_id=... - poll for the
    // minted codes the same way every solo guide's own page does, since
    // they don't exist yet at the exact moment Stripe redirects back.
    const [postPurchase, setPostPurchase] = useState(null); // null | 'checking' | 'ready' | 'error'
    const [purchasedGuides, setPurchasedGuides] = useState([]);

    useEffect(() => {
        const params = new URLSearchParams(window.location.search);
        if (params.get("purchase") === "success" && params.get("session_id")) {
            const sessionId = params.get("session_id");
            setPostPurchase("checking");
            let cancelled = false;
            let attempts = 0;
            const poll = async () => {
                if (cancelled) return;
                attempts++;
                try {
                    const res = await fetch(`${PROXY_BASE}/guides/status?session_id=${encodeURIComponent(sessionId)}`);
                    const data = await res.json();
                    if (data.success && data.ready && Array.isArray(data.guides) && data.guides.length > 0) {
                        setPurchasedGuides(data.guides);
                        setPostPurchase("ready");
                        window.history.replaceState({}, "", window.location.pathname);
                        return;
                    }
                } catch (e) { /* keep polling until attempts run out */ }
                if (attempts < 12 && !cancelled) setTimeout(poll, 1500);
                else if (!cancelled) setPostPurchase("error");
            };
            poll();
            return () => { cancelled = true; };
        }
    }, []);

    const toggleGuide = (key) => {
        setSelected(prev => {
            const next = new Set(prev);
            if (next.has(key)) next.delete(key);
            else next.add(key);
            return next;
        });
    };

    const openGuide = (guide) => {
        try { localStorage.setItem(guide.localStorageKey, guide.code); } catch (e) {}
        const catalogEntry = GUIDES_CATALOG.find(g => g.key === guide.guide);
        window.location.href = catalogEntry ? catalogEntry.href : "guides.html";
    };

    const handleBuyBundle = async () => {
        if (selected.size === 0) return;
        setPurchaseLoading(true);
        setPurchaseError(null);
        try {
            const idToken = await getIdToken();
            const res = await fetch(`${PROXY_BASE}/guides/checkout`, {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify({ guides: [...selected], email: authUser?.email || undefined })
            });
            const data = await res.json();
            if (!data.success) {
                setPurchaseError(data.error?.description || "Couldn't start checkout - please try again.");
                setPurchaseLoading(false);
                return;
            }
            window.location.href = data.url;
        } catch (e) {
            setPurchaseError("Couldn't reach the server - check your connection and try again.");
            setPurchaseLoading(false);
        }
    };

    const visibleGuides = filter === "all" ? GUIDES_CATALOG : GUIDES_CATALOG.filter(g => g.key === filter);
    const bundleCount = selected.size;
    const bundlePrice = bundleCount > 0 ? BUNDLE_PRICES_PENCE[bundleCount] : 0;
    const soloEquivalent = bundleCount * SOLO_PRICE_PENCE;
    const savings = soloEquivalent - bundlePrice;

    return (
        <div className="min-h-screen bg-[#f8fafc] flex flex-col">
            <Navbar />
            <main className="flex-1 max-w-5xl mx-auto w-full px-4 pt-28 pb-32">

                {postPurchase && (
                    <div className="mb-8 bg-white border border-slate-200 rounded-3xl shadow-sm p-6 md:p-8">
                        {postPurchase === "checking" && (
                            <p className="text-center text-slate-400 text-sm font-bold py-6">Finalising your purchase&hellip;</p>
                        )}
                        {postPurchase === "error" && (
                            <p className="text-center text-sm text-red-600 font-bold py-6">
                                That's taking longer than expected - if you were charged, check <a href="account.html" className="underline">your account</a> in a minute or two, your codes will appear there automatically.
                            </p>
                        )}
                        {postPurchase === "ready" && (
                            <div>
                                <p className="text-[10px] font-black uppercase tracking-widest text-emerald-600 mb-2">Purchase complete</p>
                                <h2 className="text-xl md:text-2xl font-black tracking-tight text-slate-900 mb-4">
                                    {purchasedGuides.length === 1 ? "Your guide is ready" : `Your ${purchasedGuides.length} guides are ready`}
                                </h2>
                                <div className="space-y-2">
                                    {purchasedGuides.map(g => (
                                        <div key={g.guide} className="border border-slate-200 rounded-2xl p-4 flex items-center justify-between gap-3">
                                            <div className="min-w-0">
                                                <p className="font-bold text-slate-900 truncate">{g.name}</p>
                                                <p className="font-mono text-xs text-slate-400 tracking-wide">{g.code}</p>
                                            </div>
                                            <button onClick={() => openGuide(g)} className="shrink-0 bg-slate-900 hover:bg-slate-800 text-white font-black uppercase text-[10px] tracking-widest px-4 py-2.5 rounded-lg transition-colors">
                                                Open guide &rarr;
                                            </button>
                                        </div>
                                    ))}
                                </div>
                                <p className="text-xs text-slate-400 mt-4">Every code above is also saved to <a href="account.html" className="underline">your account</a> if you're signed in with the email you checked out with.</p>
                            </div>
                        )}
                    </div>
                )}

                <div className="text-center mb-10">
                    <span className="inline-flex items-center gap-2 text-sky-500 font-black uppercase text-xs tracking-[0.3em] mb-4">
                        <Icon name="book" size={16} />
                        Field Guides
                    </span>
                    <h1 className="text-3xl md:text-5xl font-black tracking-tighter leading-none mb-4">Five guides. Your gear, your software.</h1>
                    <p className="text-sm md:text-base text-slate-500 max-w-xl mx-auto">
                        Each guide is a downloadable PDF customised to your own camera and editing software. Buy one solo, or select a few below and save.
                    </p>
                </div>

                <div className="flex flex-wrap justify-center gap-2 mb-8">
                    <button onClick={() => setFilter("all")} className={`px-4 py-2 rounded-full text-xs font-black uppercase tracking-widest transition-colors ${filter === "all" ? "bg-slate-900 text-white" : "bg-white text-slate-500 border border-slate-200 hover:bg-slate-50"}`}>
                        All guides
                    </button>
                    {GUIDES_CATALOG.map(g => (
                        <button key={g.key} onClick={() => setFilter(g.key)} className={`px-4 py-2 rounded-full text-xs font-black uppercase tracking-widest transition-colors ${filter === g.key ? "bg-slate-900 text-white" : "bg-white text-slate-500 border border-slate-200 hover:bg-slate-50"}`}>
                            {g.title.replace(" Field Guide", "")}
                        </button>
                    ))}
                </div>

                <div className="grid sm:grid-cols-2 gap-4 mb-10">
                    {visibleGuides.map(g => {
                        const isSelected = selected.has(g.key);
                        return (
                            <div key={g.key} className={`bg-white border rounded-3xl shadow-sm p-6 transition-colors ${isSelected ? "border-sky-400 ring-1 ring-sky-200" : "border-slate-200"}`}>
                                <div className="flex items-start justify-between gap-3 mb-3">
                                    <span className="w-10 h-10 rounded-xl bg-sky-50 text-sky-600 flex items-center justify-center shrink-0">
                                        <Icon name={g.icon} size={18} />
                                    </span>
                                    <label className="flex items-center gap-2 shrink-0">
                                        <input type="checkbox" checked={isSelected} onChange={() => toggleGuide(g.key)} className="w-4 h-4" />
                                        <span className="text-[10px] font-black uppercase tracking-widest text-slate-400">Bundle</span>
                                    </label>
                                </div>
                                <h2 className="text-base font-black tracking-tight text-slate-900 mb-1.5">{g.title}</h2>
                                <p className="text-xs text-slate-500 leading-relaxed mb-4">{g.blurb}</p>
                                <div className="flex items-center justify-between">
                                    <span className="text-xs font-bold text-slate-400">{formatGBP(SOLO_PRICE_PENCE)} solo</span>
                                    <a href={g.href} className="text-[11px] font-black uppercase tracking-widest text-sky-600 hover:text-sky-700">
                                        View guide &rarr;
                                    </a>
                                </div>
                            </div>
                        );
                    })}
                </div>

            </main>

            {bundleCount > 0 && (
                <div className="fixed bottom-0 inset-x-0 bg-white border-t border-slate-200 shadow-[0_-8px_24px_rgba(15,23,42,0.06)] z-20" style={{ paddingBottom: "env(safe-area-inset-bottom, 0px)" }}>
                    <div className="max-w-5xl mx-auto px-4 py-4 flex flex-col sm:flex-row sm:items-center justify-between gap-3">
                        <div>
                            <p className="text-sm font-black text-slate-900">
                                {bundleCount} guide{bundleCount > 1 ? "s" : ""} selected &middot; <span className="text-sky-600">{formatGBP(bundlePrice)}</span>
                            </p>
                            {savings > 0 && (
                                <p className="text-xs text-emerald-600 font-bold">Save {formatGBP(savings)} vs. buying separately ({formatGBP(soloEquivalent)})</p>
                            )}
                            {purchaseError && <p className="text-xs text-red-600 font-bold mt-1">{purchaseError}</p>}
                        </div>
                        <button onClick={handleBuyBundle} disabled={purchaseLoading} className="bg-slate-900 hover:bg-slate-800 disabled:opacity-50 text-white font-black uppercase text-xs tracking-widest py-3 px-6 rounded-xl transition-colors shrink-0">
                            {purchaseLoading ? "Redirecting to checkout…" : `Buy ${bundleCount} Guide${bundleCount > 1 ? "s" : ""} — ${formatGBP(bundlePrice)}`}
                        </button>
                    </div>
                </div>
            )}
        </div>
    );
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
