---
import SiteFooter from "../components/royal-pop/SiteFooter.astro";
import { colorways, defaultColorway } from "../data/royalPop";
import BaseLayout from "../layouts/BaseLayout.astro";
import styles from "./checkout.module.scss";

const finishOptions = [
	{ id: "silver", label: "Silver", note: "Classic brushed 316L steel" },
	{ id: "black-pvd", label: "Black PVD", note: "Stealth satin hardware" },
	{ id: "rose-gold", label: "Rose Gold", note: "Warm contrast finish" },
];

const pricePerKit = 49.99;
const retailPerKit = 89.99;
const defaultFinish = finishOptions[0];
const stripePublishableKey = process.env.STRIPE_PUBLISHABLE_KEY ?? "";
const stripePriceId = process.env.STRIPE_PRICE_ID ?? "price_1TkPnvCpoCwKMSycHiQBPVms";
const apiBaseUrl = process.env.API_BASE_URL || (import.meta.env.PROD ? "" : "http://localhost:8081");
const detailsStorageKey = "royal-pop-checkout-details";
---

<BaseLayout
	title="Royal Pop Checkout"
	description="Review your configuration and complete your Royal Pop preorder checkout."
	noindex={true}
>
	<main class={styles.checkoutPage} data-checkout-page>
		<header class={styles.topbar}>
			<div class={styles.topbarInner}>
				<a href="/details" class={styles.backLink} data-back-link>Back to details</a>

				<div class={styles.progress} aria-label="Purchase steps">
					<span>1. Configure</span>
					<span>2. Details</span>
					<span class={styles.progressActive}>3. Review &amp; Pay</span>
				</div>

				<p class={styles.helpText}>Final review &amp; payment</p>
			</div>
		</header>

		<section class={styles.hero}>
			<div class={styles.heroInner}>
				<div>
					<p class={styles.eyebrow}>Review &amp; Pay</p>
					<h1 class={styles.heroTitle}>Review your configuration and complete payment.</h1>
					<p class={styles.heroBody}>Review your selected kit, check the total, and choose how you want to complete your preorder.</p>
				</div>

				<div class={styles.heroMeta}>
					<div>
						<strong>Review stage</strong>
						<span>Check your selected kit, pricing, and preorder summary before submission.</span>
					</div>
					<div>
						<strong>Payment next</strong>
						<span>Choose the payment route that fits you best before you place the request.</span>
					</div>
					<div>
						<strong>Everything in one place</strong>
						<span>Your configuration, details, and final total stay visible here for one last check.</span>
					</div>
				</div>
			</div>
		</section>

		<section class={styles.checkoutSection}>
			<div class={styles.checkoutGrid}>
				<aside class={styles.summaryRail}>
					<div class={styles.summarySticky}>
						<div class={styles.orderCard}>
							<div class={styles.orderHeader}>
								<div>
									<p class={styles.sectionKicker}>Order summary</p>
									<h2>Your cart</h2>
								</div>
								<p class={styles.priceNow} data-summary-total>Updating…</p>
							</div>

							<div class={styles.cartList} data-cart-items>
								<div class={styles.cartItemEmpty}>Your cart is empty.</div>
							</div>

							<div class={styles.orderRows}>
								<div class={styles.orderRow}>
									<span>Kits in cart</span>
									<strong data-summary-quantity>0 kits</strong>
								</div>
								<div class={styles.orderRow}>
									<span>Early Bird total</span>
									<strong data-summary-total-inline>Updating…</strong>
								</div>
							</div>

						</div>

						<div class={styles.assuranceCard}>
							<h3>Before you submit</h3>
						<ul>
						<li>Review your chosen colourway and quantity one last time.</li>
						<li>Zero-stock configurations stay open as preorder requests until the next batch is assigned.</li>
						<li>You will receive install guidance and fit support after confirmation.</li>
						</ul>
						</div>
					</div>
				</aside>

				<div class={styles.formColumn}>
					<section class={styles.panel}>
						<div class={styles.panelHeader}>
							<p class={styles.stepCount}>Step 3A</p>
							<h2>Payment method</h2>
							<p>Choose how you would like to pay and complete your preorder securely with Stripe.</p>
						</div>

						<div class={styles.paymentShell} data-payment-shell>
							<div class={styles.paymentPanel} data-payment-panel="card">
							<div class={styles.paymentPanelHeader}>
								<div>
									<strong>Card payment</strong>
									<span>Use the secure payment form below to enter your card or any other supported payment method available for your region.</span>
								</div>
								<p>Secure</p>
							</div>

								<div class={styles.stripeMount} data-stripe-payment-element data-stripe-mount="card">
									<div class={styles.stripeLoadingState} data-stripe-loading>
										<div class={styles.stripeSpinner} aria-hidden="true"></div>
									<div class={styles.stripeLoadingCopy}>
										<p class={styles.stripeMountLabel}>Loading secure card form…</p>
										<p class={styles.stripeMountBody}>Preparing your secure payment form. This usually takes a moment.</p>
									</div>
										<div class={styles.stripeSkeletonGroup} aria-hidden="true">
											<span class={styles.stripeSkeletonLine}></span>
											<span class={styles.stripeSkeletonLine}></span>
											<span class={styles.stripeSkeletonLine}></span>
										</div>
									</div>

									<div class={styles.stripeReadyState} data-stripe-ready hidden>
										<p class={styles.stripeMountLabel}>Secure payment form</p>
										<p class={styles.stripeMountBody}>Enter your payment details below. Billing details and any required authentication will appear automatically.</p>
										<div data-stripe-element-host="card"></div>
									</div>
								</div>

								<div class={styles.paymentMetaRow}>
									<div class={styles.paymentMetaCard}>
										<strong>Accepted payment options</strong>
										<span>Your available cards and payment methods will appear automatically based on your device and location.</span>
									</div>
									<div class={styles.paymentMetaCard}>
										<strong>Secure authentication</strong>
										<span>Billing fields and any required verification steps are handled securely during checkout.</span>
									</div>
								</div>
							</div>

							<div class={styles.paymentStatusRow}>
								<div class={styles.paymentStatusCard}>
									<strong>Stripe status</strong>
									<p class={styles.paymentStatusPill} data-payment-status-pill>Initializing</p>
									<span data-payment-status-copy>Stripe is preparing a secure checkout surface for this payment method.</span>
								</div>
								<div class={styles.paymentStatusCard}>
									<strong>Secure mount point</strong>
									<span data-stripe-errors>No payment errors. Stripe validation and mount feedback will appear here if anything blocks checkout.</span>
									<button type="button" class={styles.paymentRetryButton} data-stripe-retry hidden>Retry payment form</button>
								</div>
							</div>
						</div>
					</section>

					<section class={styles.panel}>
						<div class={styles.panelHeader}>
							<p class={styles.stepCount}>Step 3B</p>
							<h2>Review your preorder</h2>
							<p>Use this step to confirm the product build and pricing before the final submit state.</p>
						</div>

						<div class={styles.stack}>
							<div class={styles.optionCard}>
								<div>
									<strong>Selected kits</strong>
									<span data-summary-colorway>{defaultColorway.name}</span>
								</div>
								<p data-summary-quantity>1 kit</p>
							</div>

							<div class={styles.optionCard}>
								<div>
									<strong>Configuration summary</strong>
									<span><span data-summary-style>{defaultColorway.styleText}</span></span>
								</div>
								<p data-summary-total-inline>Updating…</p>
							</div>
						</div>
					</section>

					<section class={styles.panel}>
						<div class={styles.panelHeader}>
							<p class={styles.stepCount}>Final review</p>
							<h2>Confirm your preorder request</h2>
							<p>Confirm the essentials below before you send your preorder request.</p>
						</div>

						<div class={styles.reviewCard}>
							<label class={styles.checkboxRow}>
								<input type="checkbox" data-review-confirmation />
								<span>I’ve reviewed my configuration, quantity, and total.</span>
							</label>

							<label class={styles.checkboxRow}>
								<input type="checkbox" />
								<span>I’m happy to receive preorder updates and shipping news by email.</span>
							</label>
						</div>

						<div class={styles.actions}>
							<a href="/details" class={styles.secondaryCta}>Back to details</a>
							<button type="button" class={styles.primaryCta} data-go-thank-you disabled aria-disabled="true">Final payment stays locked for now</button>
						</div>

						<p class={styles.footnote} data-checkout-footnote>Please confirm that you have reviewed your configuration, quantity, and total before completing payment.</p>
					</section>
				</div>
			</div>
		</section>

		<SiteFooter />

			<script is:inline src="/scripts/royal-pop-cart.js"></script>
			<script define:vars={{ colorways, defaultColorway, finishOptions, pricePerKit, retailPerKit, stripePublishableKey, stripePriceId, apiBaseUrl, detailsStorageKey, cartItemClass: styles.cartItem, cartItemImageWrapClass: styles.cartItemImageWrap, cartItemBodyClass: styles.cartItemBody, cartItemTitleClass: styles.cartItemTitle, cartItemSubtitleClass: styles.cartItemSubtitle, cartItemMetaClass: styles.cartItemMeta, cartItemFooterClass: styles.cartItemFooter, cartItemPriceClass: styles.cartItemPrice, cartItemRemoveClass: styles.cartItemRemove, cartItemEmptyClass: styles.cartItemEmpty }}>
				const { getCartCount, loadCart, removeCartItem } = window.RoyalPopCart || {};
				const STRIPE_JS_URL = "https://js.stripe.com/v3/";
				const normalizedApiBaseUrl = String(apiBaseUrl || "").replace(/\/$/, "");
				const formatGBP = (value) => `£${Number(value || 0).toFixed(2)}`;
				const bakedPricePerKit = Number(pricePerKit || 0);
				const bakedRetailPerKit = Number(retailPerKit || 0);
				const fallbackColorway = defaultColorway || colorways[0] || {
					id: "default",
					name: "Royal Pop",
					subtitle: "Selected configuration",
					styleText: "Configuration selected",
					previewBackground: "linear-gradient(180deg, #f5f5f7 0%, #eeeeef 100%)",
					cardImage: "",
				};
				let currentPricePerKit = null;
				let currentRetailPerKit = null;
				let pricingLoaded = false;

				const ensureStripeJS = async () => {
					if (window.Stripe) return window.Stripe;

					const existingScript = document.querySelector(`script[src="${STRIPE_JS_URL}"]`);
					if (existingScript) {
						await new Promise((resolve, reject) => {
							if (window.Stripe) {
								resolve();
								return;
							}

							existingScript.addEventListener("load", resolve, { once: true });
							existingScript.addEventListener("error", () => reject(new Error("Failed to load Stripe.js.")), { once: true });
						});
						return window.Stripe;
					}

					await new Promise((resolve, reject) => {
						const script = document.createElement("script");
						script.src = STRIPE_JS_URL;
						script.async = true;
						script.onload = resolve;
						script.onerror = () => reject(new Error("Failed to load Stripe.js."));
						document.head.appendChild(script);
					});

					return window.Stripe;
				};

			const initCheckoutPage = () => {
				const root = document.querySelector("[data-checkout-page]");
				if (!root || root.dataset.initialized === "true") return;

				root.dataset.initialized = "true";
				if (!getCartCount || !loadCart || !removeCartItem) return;

				const colorwayMap = new Map(colorways.map((colorway) => [colorway.id, colorway]));
				const finishMap = new Map(finishOptions.map((finish) => [finish.id, finish]));

				const loadPricing = async () => {
					try {
						const response = await fetch(`${normalizedApiBaseUrl}/v1/storefront/pricing`);
						const payload = await response.json().catch(() => null);
						if (!response.ok) {
							throw new Error(payload?.error?.message || "Pricing is temporarily unavailable.");
						}

						const pricing = payload?.data || {};
						const nextUnit = Number(pricing.unitAmount || 0) / 100;
						const nextRetail = Number(pricing.retailAmount || 0) / 100;

						currentPricePerKit = nextUnit > 0 ? nextUnit : bakedPricePerKit;
						currentRetailPerKit = nextRetail > 0 ? nextRetail : bakedRetailPerKit;
					} catch (_error) {
						currentPricePerKit = bakedPricePerKit;
						currentRetailPerKit = bakedRetailPerKit;
					} finally {
						pricingLoaded = Number.isFinite(currentPricePerKit) && currentPricePerKit > 0;
						renderCart();
						updatePaymentAction();
					}
				};

				const summaryColorway = root.querySelector("[data-summary-colorway]");
				const summaryQuantity = root.querySelector("[data-summary-quantity]");
				const summaryTotal = root.querySelector("[data-summary-total]");
				const summaryTotalInline = Array.from(root.querySelectorAll("[data-summary-total-inline]"));
				const cartItemsNode = root.querySelector("[data-cart-items]");
				const backLink = root.querySelector("[data-back-link]");
				const thankYouButton = root.querySelector("[data-go-thank-you]");
				const checkoutFootnote = root.querySelector("[data-checkout-footnote]");
				const reviewConfirmationCheckbox = root.querySelector("[data-review-confirmation]");
				const paymentShell = root.querySelector("[data-payment-shell]");
				const paymentPanels = Array.from(root.querySelectorAll("[data-payment-panel]"));
				const paymentStatusPill = root.querySelector("[data-payment-status-pill]");
					const paymentStatusCopy = root.querySelector("[data-payment-status-copy]");
					const stripeErrors = root.querySelector("[data-stripe-errors]");
					const stripeRetry = root.querySelector("[data-stripe-retry]");
					const stripeCardHost = root.querySelector('[data-stripe-element-host="card"]');
					let paymentStateTimer;
				let activePaymentTab = "card";
					let stripeInstance = null;
				let stripeElements = null;
				let paymentElement = null;
				let activeClientSecret = "";
				let activeCartSignature = "";
				let activePaymentIntentId = "";
				let activePaymentAmount = 0;
				let activeSubmitEnabled = false;
				let currentPaymentState = "loading";
				let isConfirmingPayment = false;
				let paymentVerificationState = "idle";

				const loadStoredDetails = () => {
					try {
						return JSON.parse(window.sessionStorage.getItem(detailsStorageKey) || "null");
					} catch {
						return null;
					}
				};

				const hasValidSavedDetails = () => {
					try {
						const details = loadStoredDetails();
						if (!details || typeof details !== "object") return false;

						const email = typeof details.email === "string" ? details.email.trim() : "";
						const phone = typeof details.phone === "string" ? details.phone.trim() : "";
						const firstName = typeof details.firstName === "string" ? details.firstName.trim() : "";
						const lastName = typeof details.lastName === "string" ? details.lastName.trim() : "";
						const addressLine1 = typeof details.addressLine1 === "string" ? details.addressLine1.trim() : "";
						const city = typeof details.city === "string" ? details.city.trim() : "";
						const region = typeof details.region === "string" ? details.region.trim() : "";
						const postalCode = typeof details.postalCode === "string" ? details.postalCode.trim() : "";
						const country = typeof details.country === "string" ? details.country.trim() : "";

						if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
							return false;
						}

						if (phone.length < 7) {
							return false;
						}

						if (firstName.length < 2 || lastName.length < 2) {
							return false;
						}

						if (addressLine1.length < 5 || city.length < 2 || region.length < 2 || postalCode.length < 3 || country.length < 2) {
							return false;
						}

						return true;
					} catch {
						return false;
					}
				};

			const setPaymentTab = (tab = "card") => {
				activePaymentTab = tab;

				paymentPanels.forEach((panel) => {
					panel.hidden = panel.dataset.paymentPanel !== "card";
				});

				updatePaymentAction();
			};

					const clearMountedElements = () => {
						if (paymentElement) {
							paymentElement.destroy();
							paymentElement = null;
						}

						if (stripeCardHost) {
							stripeCardHost.innerHTML = "";
						}

				stripeElements = null;
				activeClientSecret = "";
			};

			const resetPaymentIntentSession = () => {
				clearMountedElements();
				activePaymentIntentId = "";
				activePaymentAmount = 0;
				activeSubmitEnabled = false;
				paymentVerificationState = "idle";
				isConfirmingPayment = false;
			};

					const getRawCartItems = () => loadCart().map((item) => ({
						id: item.id,
						style: item.style,
						colorwayId: item.colorwayId,
						finishId: item.finishId,
						quantity: Math.max(1, Number(item.quantity || 1)),
					}));

					const getCartSignature = (items) => items
						.map((item) => [item.style, item.colorwayId, item.finishId, item.quantity].join(":"))
						.sort()
						.join("|");

			const requestPaymentIntent = async (items, tab) => {
				const customer = loadStoredDetails();
				if (!customer) {
					throw new Error("We could not find your saved contact and shipping details. Please return to the details step and try again.");
				}

					const response = await fetch(`${normalizedApiBaseUrl}/v1/checkout/payment-intent`, {
						method: "POST",
							headers: {
								"Content-Type": "application/json",
							},
							body: JSON.stringify({
								items,
								customer,
								paymentMethod: tab,
							}),
						});

						const payload = await response.json().catch(() => null);
						if (!response.ok) {
							throw new Error(payload?.error?.message || "The backend could not create a Stripe PaymentIntent.");
						}

				return payload?.data || null;
			};

			const requestPaymentStatus = async (paymentIntentId) => {
				const response = await fetch(`${normalizedApiBaseUrl}/v1/checkout/payment-intent/${encodeURIComponent(paymentIntentId)}`);
				const payload = await response.json().catch(() => null);

				if (!response.ok) {
					throw new Error(payload?.error?.message || "The backend could not load the Stripe payment status.");
				}

				return payload?.data || null;
			};

			const updatePaymentAction = () => {
				if (!thankYouButton) return;

				const total = Number.isFinite(currentPricePerKit) ? currentPricePerKit * getCartCount() : 0;
				const hasReviewedConfiguration = Boolean(reviewConfirmationCheckbox?.checked);
				let label = "Complete payment";
				let disabled = true;
				let footnote = "Please confirm that you have reviewed your configuration, quantity, and total before completing payment.";

				if (isConfirmingPayment) {
					label = "Confirming payment…";
					footnote = "Your payment is being confirmed securely. Please do not refresh this page.";
				} else if (paymentVerificationState === "pending") {
					label = "Waiting for webhook verification…";
					footnote = "Payment submitted. We are waiting for final confirmation from Stripe before redirecting you.";
				} else if (paymentVerificationState === "timed_out" && activePaymentIntentId) {
					label = "Check payment verification again";
					disabled = false;
					footnote = "Stripe may still be finalizing confirmation. Check again in a moment.";
				} else if (currentPaymentState === "loading") {
					label = "Loading Stripe form…";
					footnote = "Preparing your secure payment form.";
				} else if (!pricingLoaded) {
					label = "Loading pricing…";
					footnote = "Fetching the latest Royal Pop pricing from the backend.";
				} else if (!hasReviewedConfiguration) {
					label = "Review your configuration to continue";
					footnote = "Tick the review checkbox before completing payment.";
				} else if (activeSubmitEnabled && currentPaymentState === "ready" && stripeElements && paymentElement && getCartCount() > 0) {
					label = `Complete payment · ${formatGBP(total)}`;
					disabled = false;
					footnote = "Your payment will be processed securely and finalized after Stripe confirms completion.";
				} else if (currentPaymentState === "ready") {
					label = "Payment form needs attention";
					footnote = "The payment form is visible, but it is not ready to submit yet. Please refresh or try again in a moment.";
				}

				thankYouButton.textContent = label;
				thankYouButton.disabled = disabled;
				thankYouButton.setAttribute("aria-disabled", String(disabled));

				if (checkoutFootnote) {
					checkoutFootnote.textContent = footnote;
				}
			};

					const ensureCardElementMounted = (clientSecret) => {
						if (!stripeInstance) {
							throw new Error("Stripe frontend instance is not ready yet.");
						}

						if (!stripeCardHost) {
							throw new Error("Missing card mount host in checkout UI.");
						}

						if (!stripeElements || activeClientSecret !== clientSecret) {
							clearMountedElements();
							stripeElements = stripeInstance.elements({ clientSecret });
							activeClientSecret = clientSecret;
						}

						if (!paymentElement) {
							paymentElement = stripeElements.create("payment");
							paymentElement.mount(stripeCardHost);
						}
					};

			const setPaymentState = (state, detailMessage = "") => {
				currentPaymentState = state;
				if (paymentShell) paymentShell.dataset.paymentState = state;

					const activePanel = paymentPanels.find((panel) => panel.dataset.paymentPanel === activePaymentTab && !panel.hidden);
					const activeLoading = activePanel?.querySelector("[data-stripe-loading]");
					const activeReady = activePanel?.querySelector("[data-stripe-ready]");

					if (activeLoading) activeLoading.hidden = state !== "loading";
					if (activeReady) activeReady.hidden = state === "loading";

					if (paymentStatusPill) {
						paymentStatusPill.textContent = state === "loading"
							? "Initializing"
							: state === "error"
								? "Needs attention"
								: state === "awaiting-backend"
									? "Frontend ready"
									: "Ready";
					}

					if (paymentStatusCopy) {
						paymentStatusCopy.textContent = state === "loading"
							? "Stripe is preparing a secure checkout surface for this payment method."
							: state === "error"
								? "Stripe could not finish preparing the payment surface. Retry the mount or switch methods."
								: state === "awaiting-backend"
									? "Your payment is being finalized. We’ll update this page as soon as Stripe confirms the result."
									: "Your secure payment form is ready.";
					}

					if (stripeErrors) {
						stripeErrors.textContent = state === "error"
							? detailMessage || "We couldn’t load the secure payment form. Please try again or switch payment methods."
							: state === "awaiting-backend"
								? detailMessage || "Waiting for final confirmation from Stripe."
								: detailMessage || "No payment errors. Stripe validation and mount feedback will appear here if anything blocks checkout.";
					}

				if (stripeRetry) {
					stripeRetry.hidden = state !== "error";
				}

				updatePaymentAction();
			};

			const waitForWebhookVerification = async (paymentIntentId, options = {}) => {
				const timeoutMs = options.timeoutMs || 25000;
				const intervalMs = options.intervalMs || 1500;
				const deadline = Date.now() + timeoutMs;
				let latestStatus = null;

				while (Date.now() <= deadline) {
					latestStatus = await requestPaymentStatus(paymentIntentId);

					if (latestStatus?.verified && latestStatus?.webhookStatus === "succeeded") {
						return { outcome: "verified", status: latestStatus };
					}

					if (["failed", "canceled"].includes(latestStatus?.webhookStatus) || ["canceled", "requires_payment_method"].includes(latestStatus?.stripeStatus)) {
						return { outcome: "failed", status: latestStatus };
					}

					await new Promise((resolve) => window.setTimeout(resolve, intervalMs));
				}

				return { outcome: "timeout", status: latestStatus };
			};

			const handleVerificationCheck = async (paymentIntentId) => {
				paymentVerificationState = "pending";
				setPaymentState("awaiting-backend", "Payment submitted to Stripe. Waiting for final confirmation.");

				try {
					const result = await waitForWebhookVerification(paymentIntentId);

					if (result.outcome === "verified") {
						paymentVerificationState = "idle";
						setPaymentState("ready", result.status?.message || "Stripe confirmed your payment and updated the order record.");
						window.location.href = `/thank-you/?payment_intent=${encodeURIComponent(paymentIntentId)}`;
						return;
					}

					if (result.outcome === "failed") {
						paymentVerificationState = "idle";
						showPaymentError(result.status?.message || "Stripe did not verify the payment.");
						return;
					}

					paymentVerificationState = "timed_out";
					setPaymentState("awaiting-backend", result.status?.message || "Still waiting for Stripe to finish webhook confirmation.");
				} catch (error) {
					paymentVerificationState = "timed_out";
					showPaymentError(error instanceof Error ? error.message : "We could not verify the Stripe payment status yet.");
				}
			};

			const beginPaymentMount = async (tab) => {
				window.clearTimeout(paymentStateTimer);
				setPaymentTab(tab);
				paymentVerificationState = "idle";
				isConfirmingPayment = false;
				setPaymentState("loading");

					try {
						const items = getRawCartItems();
						const cartSignature = getCartSignature(items);
						if (!items.length) {
							throw new Error("Add at least one Royal Pop kit before loading the Stripe payment form.");
						}

					if (!stripePublishableKey) {
						throw new Error("Secure payment is not configured correctly right now. Please try again later.");
					}

						const StripeConstructor = await ensureStripeJS();
						if (!StripeConstructor) {
							throw new Error("Stripe.js loaded, but the Stripe constructor was unavailable.");
						}

						stripeInstance = stripeInstance || StripeConstructor(stripePublishableKey);
						if (!stripeInstance) {
							throw new Error("Stripe frontend initialization returned an empty instance.");
						}

					if (cartSignature !== activeCartSignature) {
						resetPaymentIntentSession();
						activeCartSignature = cartSignature;
					}

					if (activeCartSignature === cartSignature && activeClientSecret && activePaymentIntentId) {
						if (tab === "card") {
							ensureCardElementMounted(activeClientSecret);
						}

						paymentStateTimer = window.setTimeout(() => {
							setPaymentState("ready", `Your secure payment session is ready for ${formatGBP(Number(activePaymentAmount || 0) / 100)}.`);
						}, 200);
						return;
					}

					const intentData = await requestPaymentIntent(items, tab);
					if (!intentData?.clientSecret) {
						throw new Error("The backend response did not include a Stripe client secret.");
					}

					activePaymentIntentId = intentData.paymentIntentId || "";
					activePaymentAmount = Number(intentData.amount || 0);
					activeSubmitEnabled = Boolean(intentData.submitEnabled);

					if (tab === "card") {
						ensureCardElementMounted(intentData.clientSecret);
						}

					paymentStateTimer = window.setTimeout(() => {
					setPaymentState("ready", `Your secure payment session is ready for ${formatGBP(Number(intentData.amount || 0) / 100)}.`);
				}, 400);
					} catch (error) {
						showPaymentError(error instanceof Error ? error.message : "We couldn’t initialize Stripe on the frontend.");
					}
				};

				const showPaymentError = (message) => {
					window.clearTimeout(paymentStateTimer);
					setPaymentState("error", message);
				};

				const renderCart = () => {
					const hasPricing = Number.isFinite(currentPricePerKit) && currentPricePerKit > 0;
					const hasRetailPricing = Number.isFinite(currentRetailPerKit) && currentRetailPerKit > 0;
					const cartItems = loadCart().map((item) => ({
						...item,
						quantity: Math.max(1, Number(item.quantity || 1)),
						colorway: colorwayMap.get(item.colorwayId) || fallbackColorway,
						finish: finishMap.get(item.finishId) || defaultFinish,
					}));
					const totalQuantity = cartItems.reduce((sum, item) => sum + item.quantity, 0);
					const total = hasPricing ? currentPricePerKit * totalQuantity : 0;
					if (summaryColorway) summaryColorway.textContent = cartItems.map((item) => item.colorway.name).join(", ") || "No kits in cart";
					if (summaryQuantity) summaryQuantity.textContent = `${totalQuantity} ${totalQuantity === 1 ? "kit" : "kits"}`;
					if (summaryTotal) summaryTotal.textContent = hasPricing ? formatGBP(total) : "Updating…";
					summaryTotalInline.forEach((node) => {
						node.textContent = hasPricing ? formatGBP(total) : "Updating…";
					});

					const isEmpty = totalQuantity === 0;

					const nextCartSignature = getCartSignature(getRawCartItems());
					if (nextCartSignature !== activeCartSignature) {
						resetPaymentIntentSession();
						activeCartSignature = "";
					}

					if (!cartItemsNode) return;

					if (isEmpty) {
						cartItemsNode.innerHTML = `<div class="${cartItemEmptyClass}">Your cart is empty. Go back to Details or Configure to add a kit.</div>`;
						updatePaymentAction();
						return;
					}

					cartItemsNode.innerHTML = cartItems
						.map(
							(item) => `
								<article class="${cartItemClass}">
									<div class="${cartItemImageWrapClass}" style="background:${item.colorway.previewBackground}">
										<img src="${item.colorway.cardImage}" alt="${item.colorway.name} kit preview" />
									</div>
									<div class="${cartItemBodyClass}">
										<div>
											<strong class="${cartItemTitleClass}">${item.colorway.name}</strong>
											<p class="${cartItemSubtitleClass}">${item.colorway.subtitle}</p>
											<p class="${cartItemMetaClass}">${item.colorway.styleText}</p>
											<p class="${cartItemMetaClass}">${item.quantity} ${item.quantity === 1 ? "kit" : "kits"} · Matched configuration</p>
										</div>
										<div class="${cartItemFooterClass}">
									<strong class="${cartItemPriceClass}">${hasPricing ? formatGBP(currentPricePerKit * item.quantity) : "Updating…"}</strong>
											<button type="button" class="${cartItemRemoveClass}" data-remove-cart-item="${item.id}">Remove</button>
										</div>
									</div>
								</article>`,
						)
						.join("");

					updatePaymentAction();
				};

				if (backLink) backLink.setAttribute("href", "/details");

				const savedDetailsValid = hasValidSavedDetails();

				if (cartItemsNode) {
					cartItemsNode.addEventListener("click", (event) => {
						const button = event.target.closest("[data-remove-cart-item]");
						if (!button) return;

						const { removeCartItem: itemId } = button.dataset;
						if (!itemId) return;

						removeCartItem(itemId);
						renderCart();

						if (getCartCount() > 0) {
							beginPaymentMount(activePaymentTab);
						} else {
							showPaymentError("Add at least one Royal Pop kit before loading the Stripe payment form.");
						}
					});
				}

				if (thankYouButton) {
					thankYouButton.addEventListener("click", async () => {
						if (paymentVerificationState === "timed_out" && activePaymentIntentId) {
							await handleVerificationCheck(activePaymentIntentId);
							return;
						}

						if (!reviewConfirmationCheckbox?.checked) {
							showPaymentError("Please confirm that you have reviewed your configuration, quantity, and total before completing payment.");
							return;
						}

						if (!activeSubmitEnabled) {
							showPaymentError("Payment confirmation is not available right now. Please refresh and try again.");
							return;
						}

						if (!stripeInstance || !stripeElements || !paymentElement || !activePaymentIntentId) {
							showPaymentError("Stripe is not ready to confirm this payment yet. Reload the card form and try again.");
							return;
						}

						try {
							isConfirmingPayment = true;
							setPaymentState("loading", "Confirming your payment now.");

							const submitResult = await stripeElements.submit();
							if (submitResult?.error) {
								throw new Error(submitResult.error.message || "Stripe could not validate the payment form.");
							}

							const { error, paymentIntent } = await stripeInstance.confirmPayment({
								elements: stripeElements,
								confirmParams: {
									return_url: `${window.location.origin}/thank-you/`,
								},
								redirect: "if_required",
							});

							if (error) {
								throw new Error(error.message || "Stripe could not confirm the test payment.");
							}

							activePaymentIntentId = paymentIntent?.id || activePaymentIntentId;
							isConfirmingPayment = false;
							await handleVerificationCheck(activePaymentIntentId);
						} catch (error) {
							isConfirmingPayment = false;
							paymentVerificationState = "idle";
							showPaymentError(error instanceof Error ? error.message : "Stripe could not confirm the payment.");
						}
					});
				}

				if (stripeRetry) {
					stripeRetry.addEventListener("click", () => {
						beginPaymentMount(activePaymentTab);
					});
				}

				if (reviewConfirmationCheckbox) {
					reviewConfirmationCheckbox.checked = false;
					reviewConfirmationCheckbox.addEventListener("change", () => {
						updatePaymentAction();
					});
				}

				const paymentPreviewState = new URLSearchParams(window.location.search).get("paymentState");

				if (paymentPreviewState === "error") {
					setPaymentTab("card");
					showPaymentError("We couldn’t load the secure payment form. Check your Stripe publishable key, client secret, or network connection, then try again.");
				} else if (!savedDetailsValid) {
					setPaymentTab("card");
					showPaymentError("We couldn’t confirm your saved contact and shipping details. Please return to Details, review the form, and continue again.");
				} else {
					beginPaymentMount("card");
				}

				renderCart();
				loadPricing();
			};

			initCheckoutPage();
			document.addEventListener("astro:page-load", initCheckoutPage);
		</script>
	</main>
</BaseLayout>
