"use client";

import Image from "next/image";
import { withCDN } from "@/src/lib/utils";
import { useState, useEffect, useMemo, Suspense } from "react";
import { ChevronDown, ChevronUp, Loader2, CreditCard, CalendarDays, ChevronLeft, ChevronRight, Lock } from "lucide-react";
import { useClassDetails } from "@/src/lib/context/ClassDetailsContext";
import { verifyCouponAction } from "@/src/lib/actions/couponAction";
import { submitFormAction } from "@/src/lib/actions/submitFormAction";
import { getFormsAction } from "@/src/lib/actions/formsAction";
import { getCheckoutPageDataAction } from "@/src/lib/actions/checkoutPageAction";
import { getPrivacyPolicyDataAction } from "@/src/lib/actions/privacyPolicyAction";
import { getTermsOfUseDataAction } from "@/src/lib/actions/termsOfUseAction";
import PrivacyPolicyModal from "@/src/components/ui/PrivacyPolicyModal";
import { interpolate } from "@/src/lib/utils/interpolate";
import { useLocalizedNavigation } from "@/src/lib/hooks/useLocalizedNavigation";
import { useLanguage } from "@/src/lib/context/LanguageContext";
import { resolveClasswiseAccountIdFromHostname } from "@/src/lib/utils/resolveClasswiseAccountId";
import { TextInputWithValidation, SelectDropdown } from "./FormRenderer";
import PhoneInput from "./PhoneInput";
import { useSearchParams } from "next/navigation";
import { getRegisterDetailsAction } from "@/src/lib/actions/registerDetailsAction";
import { getJSONCookie, setJSONCookie } from "@/src/lib/utils/cookies";
import { initiatePaymentAction, setupPaymentAction } from "@/src/lib/actions/paymentAction";
import { getPaymentStatusAction } from "@/src/lib/actions/paymentStatusAction";
import { formatPaymentErrorMessage } from "@/src/lib/utils/paymentErrorMessage";
import { fetchPaymentPlansAction } from "@/src/lib/actions/paymentPlansAction";
import StripePaymentFields from "./StripePaymentFields";
import RegistrationSidebar from "./RegistrationSidebar";
import StripeWalletFields from "./StripeWalletFields";
import { Elements, useStripe, useElements } from "@stripe/react-stripe-js";
import {
  extractClientSecretFromPayment,
  extractStripeAccountFromPayment,
  loadStripeConnect,
  writeStripeAccountToSession,
} from "@/src/lib/stripe/loadStripeConnect";
import { roundMoney } from "@/src/lib/utils/money";
/** Sync payment + trigger confirmation emails after client-side Stripe success (webhooks may not run locally). */
async function syncPaymentAndNotify(
  registrationId: string,
  intentId: string | null | undefined
) {
  if (!registrationId) {
    return;
  }

  await getPaymentStatusAction(registrationId, {
    paymentIntent: intentId?.startsWith("pi_") ? intentId : null,
    setupIntent: intentId?.startsWith("seti_") ? intentId : null,
  });
}

// Cookie that remembers a returning user's parent/child details (identity fields
// only — never payment/card data) so the registration form can prefill them.
const REGISTRANT_COOKIE = "ye_registrant";

const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const nameRegex = /^[a-zA-Z\s\-']*$/;


export default function RegisterProgramForm({
  zohoFranchiseId,
  stripeAccountId: initialStripeAccountId = null,
}: {
  zohoFranchiseId?: string;
  stripeAccountId?: string | null;
}) {
  const connectedAccountId = initialStripeAccountId;

  const stripePromise = useMemo(() => {
    if (!connectedAccountId) {
      return null;
    }
    return loadStripeConnect(
      process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY || "",
      connectedAccountId
    );
  }, [connectedAccountId]);

  if (!connectedAccountId || !stripePromise) {
    return (
      <section className="relative bg-transperent mt-10 py-10 px-5 xl:px-0 max-w-[1300px] mx-auto w-full">
        <div className="rounded-[15px] border border-red-200 bg-red-50 p-6 text-center text-red-700">
          Payment is not configured for this site. Please contact the franchise administrator.
        </div>
      </section>
    );
  }

  return (
    <Elements stripe={stripePromise} key={connectedAccountId}>
      <Suspense fallback={<RegisterProgramFormLoading />}>
        <RegisterProgramFormContent
          zohoFranchiseId={zohoFranchiseId}
          connectedAccountId={connectedAccountId}
        />
      </Suspense>
    </Elements>
  );
}

function RegisterProgramFormLoading() {
  return (
    <section className="relative bg-transperent mt-10 py-10 px-5 xl:px-0 max-w-[1300px] mx-auto w-full">
      <div className="flex items-center justify-center py-24">
        <Loader2 className="w-8 h-8 animate-spin text-[#0097DC]" />
      </div>
    </section>
  );
}

function RegisterProgramFormContent({
  zohoFranchiseId,
  connectedAccountId,
}: {
  zohoFranchiseId?: string;
  connectedAccountId: string;
}) {
  const stripe = useStripe();
  const elements = useElements();
  const { classDetails } = useClassDetails();
  const { push } = useLocalizedNavigation();
  const { currentLanguage } = useLanguage();
  const searchParams = useSearchParams();
  const submissionId = searchParams.get("submission_id");

  const [form, setForm] = useState<any>(null);
  const [pageContent, setPageContent] = useState<any>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [agreed, setAgreed] = useState(false);
  const [coupon, setCoupon] = useState("");
  const [isVerifyingCoupon, setIsVerifyingCoupon] = useState(false);
  const [couponData, setCouponData] = useState<any>(null);
  const [couponError, setCouponError] = useState("");
  // Hide the coupon field until the user opts in ("Do you have a coupon?").
  const [showCoupon, setShowCoupon] = useState(false);
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [submitted, setSubmitted] = useState(false);
  const [lastSubmissionId, setLastSubmissionId] = useState<string | null>(null);
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [isReadOnly, setIsReadOnly] = useState(false);
  const [cardName, setCardName] = useState("");
  const [saveCard, setSaveCard] = useState(false);
  const [paymentError, setPaymentError] = useState<string | null>(null);
  const [isProcessingPayment, setIsProcessingPayment] = useState(false);
  const [isCardComplete, setIsCardComplete] = useState(false);

  // Dynamic wallet availability state
  const [walletAvailability, setWalletAvailability] = useState({ applePay: false, googlePay: false, link: false });

  // Privacy Policy modal state
  const [isPrivacyOpen, setIsPrivacyOpen] = useState(false);
  const [isPrivacyLoading, setIsPrivacyLoading] = useState(false);
  const [privacyContent, setPrivacyContent] = useState<{ heading?: string; effectiveDate?: string; content?: string } | null>(null);
  const [privacyFetched, setPrivacyFetched] = useState(false);
  const [privacyVersion, setPrivacyVersion] = useState<number | null>(null);
  const [privacyLang, setPrivacyLang] = useState<string | null>(null);

  const openPrivacyPolicy = async () => {
    setIsPrivacyOpen(true);
    if (privacyFetched) return;
    setIsPrivacyLoading(true);
    try {
      const response = await getPrivacyPolicyDataAction(
        classDetails?.franchise_id?.toString(),
        currentLanguage,
      );
      if (response?.success && response.data) {
        const section =
          response.data.translated?.privacyPolicy ||
          response.data.default?.privacyPolicy ||
          null;
        setPrivacyContent(section);
        setPrivacyVersion(response.data.version ?? null);
        setPrivacyLang(response.data.language_code ?? null);
      }
      setPrivacyFetched(true);
    } catch (error) {
      console.error("Error fetching privacy policy:", error);
    } finally {
      setIsPrivacyLoading(false);
    }
  };

  // Terms of Use modal state
  const [isTermsOpen, setIsTermsOpen] = useState(false);
  const [isTermsLoading, setIsTermsLoading] = useState(false);
  const [termsContent, setTermsContent] = useState<{ heading?: string; effectiveDate?: string; content?: string } | null>(null);
  const [termsFetched, setTermsFetched] = useState(false);
  const [termsVersion, setTermsVersion] = useState<number | null>(null);
  const [termsLang, setTermsLang] = useState<string | null>(null);

  const openTermsOfUse = async () => {
    setIsTermsOpen(true);
    if (termsFetched) return;
    setIsTermsLoading(true);
    try {
      const response = await getTermsOfUseDataAction(
        classDetails?.franchise_id?.toString(),
        currentLanguage,
      );
      if (response?.success && response.data) {
        const section =
          (response.data.translated as any)?.termsOfUse ||
          (response.data.translated as any)?.privacyPolicy ||
          (response.data.default as any)?.termsOfUse ||
          (response.data.default as any)?.privacyPolicy ||
          null;
        setTermsContent(section);
        setTermsVersion(response.data.version ?? null);
        setTermsLang(response.data.language_code ?? null);
      }
      setTermsFetched(true);
    } catch (error) {
      console.error("Error fetching terms of use:", error);
    } finally {
      setIsTermsLoading(false);
    }
  };

  // Payment plans states
  const [showPaymentPlans, setShowPaymentPlans] = useState(false);
  const [paymentPlans, setPaymentPlans] = useState<any[]>([]);
  const [isLoadingPlans, setIsLoadingPlans] = useState(false);
  const [plansError, setPlansError] = useState("");
  const [plansPage, setPlansPage] = useState(1);
  const PLANS_PER_PAGE = 5;

  // Form states
  const [parentInfo, setParentInfo] = useState({ firstName: "", lastName: "", email: "", phone: "" });
  const [childInfo, setChildInfo] = useState({ firstName: "", lastName: "", age: "", school: "" });
  const [paymentMethod, setPaymentMethod] = useState("card");

  useEffect(() => {
    if (classDetails) {
      if (String(classDetails.payer_id) === "2") {
        setPaymentMethod("later");
      } else if (paymentMethod === "later") {
        setPaymentMethod("card");
      }
    }
  }, [classDetails?.payer_id]);

  // Check Wallet Availability globally when Stripe loads
  useEffect(() => {
    if (stripe) {
      const pr = stripe.paymentRequest({
        country: "US",
        currency: "usd",
        total: { label: "Availability Check", amount: 100 },
      });
      pr.canMakePayment().then((result) => {
        if (result) {
          setWalletAvailability({
            applePay: !!result.applePay,
            googlePay: !!result.googlePay,
            link: !!result.link,
          });
        }
      });
    }
  }, [stripe]);

  useEffect(() => {
    async function loadSubmissionDetails() {
      if (!submissionId) {
        setIsLoading(false);
        return;
      }
      setIsLoading(true);
      try {
        const response = await getRegisterDetailsAction(submissionId);
        if (response?.status && response.data?.[0]) {
          const data = response.data[0];
          const submissionData = data.submission_data;
          const formDataArray = Array.isArray(submissionData) ? submissionData : Object.values(submissionData);

          // Match each step by the fields it carries, not by a specific step label —
          // different forms (footer/global vs class-detail) use different step names.
          const pDetails = formDataArray.find((d: any) =>
            d.step_1 === "parent_details" ||
            d.step_1 === "provide_parent_info" ||
            d.step_1 === "parent_information" ||
            d.full_name ||
            ((d.email || d.email_address) && (d.phone || d.phone_number))
          );
          const cDetails = formDataArray.find((d: any) =>
            d.step_2 === "child_details" ||
            d.step_2 === "provide_your_child_info" ||
            d.childs_name || d.age || d.school || d.childs_age
          );
          const payDetails = formDataArray.find((d: any) =>
            d.step_3 === "payment_details" || d.payment_method
          );

          if (pDetails) {
            // Footer/global form saves "full_name" + "email_address"; the
            // class-detail form uses "name" + "email". Accept both.
            const [firstName, ...lastNames] = (pDetails.full_name || pDetails.name || "").split(" ");
            setParentInfo({
              firstName: firstName || "",
              lastName: lastNames.join(" ") || "",
              email: pDetails.email || pDetails.email_address || "",
              // Kept as stored (e.g. "+91 7857004975"); formatPhoneNumber would
              // reshape the country code into a US-style "(917)" grouping.
              phone: pDetails.phone || pDetails.phone_number || "",
            });
          }

          if (cDetails) {
            // Footer form uses `name` for the child; class-detail form uses `childs_name`.
            const rawChildName = cDetails.childs_name || cDetails.name || "";
            const [cFirstName, ...cLastNames] = rawChildName.split(" ");
            setChildInfo({
              firstName: cFirstName || "",
              lastName: cLastNames.join(" ") || "",
              age: cDetails.age || cDetails.childs_age || "",
              school: cDetails.school || cDetails.grade || "",
            });
          }

          if (payDetails) {
            setPaymentMethod(payDetails.payment_method || "card");
            if (payDetails.coupon_code) {
              setCoupon(payDetails.coupon_code);
              setShowCoupon(true);
            }
          }

          setIsReadOnly(true);
          setAgreed(true);
        }
      } catch (error) {
        console.error("Failed to load submission details:", error);
      } finally {
        setIsLoading(false);
      }
    }
    loadSubmissionDetails();
  }, [submissionId]);

  // Prefill parent/child details from the cookie saved on a previous submission.
  // Only for a fresh registration — when editing a specific submission the server
  // data (loadSubmissionDetails) is the source of truth.
  useEffect(() => {
    if (submissionId) return;
    const saved = getJSONCookie<{
      parent?: Partial<typeof parentInfo>;
      child?: Partial<typeof childInfo>;
    }>(REGISTRANT_COOKIE);
    if (!saved) return;
    if (saved.parent) setParentInfo((prev) => ({ ...prev, ...saved.parent }));
    if (saved.child) setChildInfo((prev) => ({ ...prev, ...saved.child }));
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [submissionId]);

  // Save the entered parent/child identity fields (NOT payment info) to a cookie
  // so a returning user's form is prefilled next time. Called on submit.
  const rememberRegistrant = () => {
    setJSONCookie(REGISTRANT_COOKIE, { parent: parentInfo, child: childInfo }, 30);
  };

  useEffect(() => {
    if (String(classDetails?.payer_id) === "2") {
      setPaymentMethod("later");
    }
  }, [classDetails]);

  useEffect(() => {
    async function fetchPlans() {
      const groupId = classDetails?.id;
      const accountId = resolveClasswiseAccountIdFromHostname(
        zohoFranchiseId,
        classDetails?.franchise
      );
      const fId = searchParams.get("franchiseeId");

      if (!groupId || !accountId) return;

      setIsLoadingPlans(true);
      try {
        const response = await fetchPaymentPlansAction(
          String(groupId),
          accountId,
          fId,
          classDetails?.franchise
        );
        if (response.success && response.data.length > 0) {
          setPaymentPlans(response.data);
        }
      } catch (err) {
        console.error("Failed to fetch plans:", err);
      } finally {
        setIsLoadingPlans(false);
      }
    }
    fetchPlans();
  }, [classDetails, zohoFranchiseId, searchParams]);

  useEffect(() => {
    async function fetchForm() {
      try {
        const response = await getFormsAction(classDetails?.franchise_id?.toString());
        if (response.success) {
          setForm(response.data);
        }
      } catch (error) {
        console.error("Error fetching form:", error);
      }
    }
    if (classDetails) fetchForm();
  }, [classDetails]);

  useEffect(() => {
    async function fetchCheckoutPage() {
      try {
        const response = await getCheckoutPageDataAction(classDetails?.franchise_id?.toString(), currentLanguage);
        if (response?.success && response.data) {
          const contentObj = response.data.translated?.checkoutPage || response.data.default?.checkoutPage;
          if (contentObj) setPageContent(contentObj);
        }
      } catch (error) {
        console.error("Error fetching checkout page data:", error);
      }
    }
    fetchCheckoutPage();
  }, [classDetails?.franchise_id, currentLanguage]);

  // Prefetch both policy versions silently so version + language_code are always
  // recorded in policy_consents even if the user never opens the popups.
  useEffect(() => {
    if (!classDetails) return;
    const fid = classDetails.franchise_id?.toString();

    if (!privacyFetched) {
      getPrivacyPolicyDataAction(fid, currentLanguage).then((response) => {
        if (response?.success && response.data) {
          const section =
            response.data.translated?.privacyPolicy ||
            response.data.default?.privacyPolicy ||
            null;
          setPrivacyContent(section);
          setPrivacyVersion(response.data.version ?? null);
          setPrivacyLang(response.data.language_code ?? null);
          setPrivacyFetched(true);
        }
      }).catch(() => {});
    }

    if (!termsFetched) {
      getTermsOfUseDataAction(fid, currentLanguage).then((response) => {
        if (response?.success && response.data) {
          const section =
            (response.data.translated as any)?.termsOfUse ||
            (response.data.translated as any)?.privacyPolicy ||
            (response.data.default as any)?.termsOfUse ||
            (response.data.default as any)?.privacyPolicy ||
            null;
          setTermsContent(section);
          setTermsVersion(response.data.version ?? null);
          setTermsLang(response.data.language_code ?? null);
          setTermsFetched(true);
        }
      }).catch(() => {});
    }
  }, [classDetails, currentLanguage]);

  const perUnitPrice = classDetails
    ? roundMoney(
      parseFloat(String(classDetails.value ?? (classDetails as { price?: string }).price ?? "0"))
    )
    : 0;
  const lessonCount = classDetails ? parseInt(String(classDetails.number_of_lessons), 10) || 1 : 1;

  const getDiscountAmount = () => {
    if (!couponData) return 0;
    if (couponData.discount_type === "percentage") {
      return roundMoney((perUnitPrice * couponData.discount) / 100);
    }
    return roundMoney(Number(couponData.discount) || 0);
  };

  const hasPaymentPlans = paymentPlans.length > 0;
  const amountDueNow = roundMoney(
    hasPaymentPlans
      ? parseFloat(paymentPlans[0]?.amount) || 0
      : Math.max(0, perUnitPrice * lessonCount - getDiscountAmount())
  );
  /** Total value of the class = unit price × number of lessons (not sum of installments). */
  const totalClassValue = roundMoney(
    Math.max(0, perUnitPrice * lessonCount - getDiscountAmount())
  );
  const paymentFrequency = String(classDetails?.payment_charges_frequency || "per_lesson").toLowerCase();
  const frequencyLabelMap: Record<string, string> = {
    weekly: "Weekly",
    monthly: "Monthly",
    daily: "Daily",
    per_lesson: "Per lesson",
  };
  const paymentFrequencyLabel = frequencyLabelMap[paymentFrequency] || paymentFrequency.replace(/_/g, " ");
  const feeBasis = String(classDetails?.fee_basis || "per_lesson").toLowerCase();
  const priceUnitSuffix = feeBasis.includes("month") ? "per month" : feeBasis.includes("week") ? "per week" : "per lesson";

  /** @deprecated use amountDueNow — kept for sidebar prop name compatibility */
  const finalPrice = amountDueNow;
  const displayPaymentAmount = amountDueNow;
  const formatAmount = (value: number) =>
    Number.isInteger(value) ? value.toString() : value.toFixed(2);

  const buildPaymentStepFields = () => ({
    step_3: "payment_details",
    payment_method: paymentMethod,
    coupon_code: couponData?.coupon_code || "",
    discount_amount: getDiscountAmount(),
    final_price: amountDueNow,
    amount_due_now: amountDueNow,
    total_class_value: totalClassValue,
    total_program_price: totalClassValue,
    per_unit_price: perUnitPrice,
    number_of_lessons: lessonCount,
    payment_charges_frequency: paymentFrequency,
    payment_frequency_label: paymentFrequencyLabel,
    price_per_lesson_display: `$${formatAmount(perUnitPrice)} ${priceUnitSuffix}`,
    installment_number: hasPaymentPlans ? 1 : null,
    installment_total: hasPaymentPlans ? paymentPlans.length : null,
  });

  const validateField = (name: string, value: string, type: string = "text", isRequired: boolean = true) => {
    let error = "";
    if (isRequired && (!value || value.trim() === "")) {
      error = "This field is required";
    } else if (value && value.trim() !== "") {
      if (type === "email" && !emailRegex.test(value)) {
        error = "Please enter a valid email address";
      } else if (type === "phone") {
        const digits = value.replace(/\D/g, "");
        if (digits.length < 10 || digits.length > 14) {
          error = "Please enter a valid phone number (10 to 14 digits)";
        }
      } else if (type === "name" && !nameRegex.test(value)) {
        error = "Should only contain letters, spaces, and hyphens";
      }
    }
    setErrors(prev => ({ ...prev, [name]: error }));
    return error === "";
  };

  const handleApplyCoupon = async () => {
    if (!coupon.trim() || !classDetails?.id) return;
    setIsVerifyingCoupon(true);
    setCouponError("");
    try {
      const response = await verifyCouponAction(coupon.trim(), classDetails.id);
      if (response.success) {
        setCouponData(response.data);
      } else {
        setCouponError(response.message || "Invalid coupon code");
        setCouponData(null);
      }
    } catch (error) {
      setCouponError("Failed to verify coupon");
    } finally {
      setIsVerifyingCoupon(false);
    }
  };

  // --- STANDARD CARD SUBMISSION ---
  const handleSubmit = async () => {
    if (isReadOnly) {
      handlePayNow();
      return;
    }

    setErrors({});
    const p1 = validateField("parent_first_name", parentInfo.firstName, "name");
    const p2 = validateField("parent_last_name", parentInfo.lastName, "name", false);
    const p3 = validateField("parent_email", parentInfo.email, "email");
    const p4 = validateField("parent_phone", parentInfo.phone, "phone");
    const c1 = validateField("child_first_name", childInfo.firstName, "name");
    const c2 = validateField("child_last_name", childInfo.lastName, "name", false);
    const c3 = validateField("child_age", childInfo.age);
    const c4 = validateField("child_school", childInfo.school);

    if (!p1 || !p2 || !p3 || !p4 || !c1 || !c2 || !c3 || !c4) {
      setErrors(prev => ({ ...prev, form: "Please fix the errors in the form before submitting." }));
      return;
    }
    if (!agreed) {
      setErrors(prev => ({ ...prev, policy: "Please agree to the Privacy Policy and Terms of Use." }));
      return;
    }
    if (paymentMethod === "card") {
      if (!cardName.trim()) {
        setErrors(prev => ({ ...prev, form: "Please enter the name on the card." }));
        return;
      }
      if (!isCardComplete) {
        setErrors(prev => ({ ...prev, form: "Please enter valid card details." }));
        return;
      }
    }

    // Wallet methods (Google Pay, Apple Pay, Link) have their own payment button
    // rendered by StripeWalletFields. Clicking the generic "Register and Pay" button
    // while a wallet method is selected must NOT submit the form — that would create a
    // registration record without any payment being processed.
    if (paymentMethod === "google" || paymentMethod === "apple" || paymentMethod === "link") {
      setErrors(prev => ({
        ...prev,
        form: "Please use the Google Pay or Apple Pay button above to complete your registration and payment.",
      }));
      return;
    }

    if (!classDetails) return;

    setIsSubmitting(true);
    try {
      const formData = [
        { step_1: "parent_details", name: `${parentInfo.firstName} ${parentInfo.lastName}`, email: parentInfo.email, phone: parentInfo.phone },
        { step_2: "child_details", "childs_name": `${childInfo.firstName} ${childInfo.lastName}`, age: childInfo.age, school: childInfo.school },
        buildPaymentStepFields(),
        {
          policy_consents: [
            { type: "privacy_policy", language_code: privacyLang, version: privacyVersion },
            { type: "terms_of_use",   language_code: termsLang,   version: termsVersion   },
          ],
        },
      ];

      const classData = {
        group_id: classDetails.id,
        franchise_id: classDetails.franchise_id,
        group_name: classDetails.group_name,
        program_name: classDetails.program?.title || classDetails.program?.name || "",
        instructor_name: classDetails.instructors?.[0]?.name || "",
        start_date: classDetails.start_date,
        start_time: classDetails.start_time,
        end_time: classDetails.end_time,
        day: classDetails.day || [],
        location: classDetails.p_o_s?.name || classDetails.p_o_s?.location || "",
        min_age: classDetails.min_age,
        max_age: classDetails.max_age,
        price: perUnitPrice,
        number_of_lessons: lessonCount,
        total_class_value: totalClassValue,
        total_program_price: totalClassValue,
        amount_due_now: amountDueNow,
        payment_charges_frequency: paymentFrequency,
        price_name: classDetails.fee_basis,
        payer_id: classDetails.payer_id,
        invoice_tax_value: classDetails.invoice_tax || classDetails.franchise?.invoice_tax_value,
        invoice_tax_label: classDetails.invoice_tax_label || classDetails.franchise?.invoice_tax_label,
        company_name: classDetails.franchise?.company_name,
        company_address: classDetails.franchise?.company_address,
      };

      const payload = {
        form_id: form?.id || "registration_form",
        form_data: formData,
        slug: "home",
        class_details: classData
      };




      const response = (await submitFormAction(payload)) as any;

      if (response.status && response.submission_id) {
        // Remember this registrant's details for next time (prefill).
        rememberRegistrant();
        setLastSubmissionId(response.submission_id);
        if (paymentMethod === "card") {
          await handlePayNow(response.submission_id);
        } else if (paymentMethod === "later") {
          // Pay-later: registration is intentionally created without upfront payment.
          push(`/thank-you/${response.submission_id}?paylater=true`);
        } else {
          // Defensive fallback — should not be reached after the guard above.
          setErrors(prev => ({
            ...prev,
            form: "Please use the wallet payment button above to complete your payment.",
          }));
        }
      } else {
        alert(response.message || "Failed to submit registration");
      }
    } catch (error) {
      console.error("Error submitting form:", error);
      alert("An error occurred. Please try again.");
    } finally {
      setIsSubmitting(false);
    }
  };

  // --- WALLET SUBMISSION (APPLE PAY / GOOGLE PAY) ---
  const handleWalletPaymentAuth = async (ev: any) => {
    setErrors({});
    setPaymentError(null);

    // 1. Validate Form First
    const p1 = validateField("parent_first_name", parentInfo.firstName, "name");
    const p2 = validateField("parent_last_name", parentInfo.lastName, "name", false);
    const p3 = validateField("parent_email", parentInfo.email, "email");
    const p4 = validateField("parent_phone", parentInfo.phone, "phone");
    const c1 = validateField("child_first_name", childInfo.firstName, "name");
    const c2 = validateField("child_last_name", childInfo.lastName, "name", false);
    const c3 = validateField("child_age", childInfo.age);
    const c4 = validateField("child_school", childInfo.school);

    if (!p1 || !p2 || !p3 || !p4 || !c1 || !c2 || !c3 || !c4) {
      setErrors(prev => ({ ...prev, form: "Please complete all required fields before using Wallet Pay." }));
      ev.complete("fail");
      return;
    }
    if (!agreed) {
      setErrors(prev => ({ ...prev, policy: "Please agree to the Privacy Policy and Terms of Use before paying." }));
      ev.complete("fail");
      return;
    }
    if (!classDetails) {
      ev.complete("fail");
      return;
    }

    setIsSubmitting(true);

    try {
      // 2. Submit Form Data
      const formData = [
        { step_1: "parent_details", name: `${parentInfo.firstName} ${parentInfo.lastName}`, email: parentInfo.email, phone: parentInfo.phone },
        { step_2: "child_details", "childs_name": `${childInfo.firstName} ${childInfo.lastName}`, age: childInfo.age, school: childInfo.school },
        buildPaymentStepFields(),
        {
          policy_consents: [
            { type: "privacy_policy", language_code: privacyLang, version: privacyVersion },
            { type: "terms_of_use",   language_code: termsLang,   version: termsVersion   },
          ],
        },
      ];

      const classData = {
        group_id: classDetails.id,
        franchise_id: classDetails.franchise_id,
        group_name: classDetails.group_name,
        program_name: classDetails.program?.title || classDetails.program?.name || "",
        instructor_name: classDetails.instructors?.[0]?.name || "",
        start_date: classDetails.start_date,
        start_time: classDetails.start_time,
        end_time: classDetails.end_time,
        day: classDetails.day || [],
        location: classDetails.p_o_s?.name || classDetails.p_o_s?.location || "",
        min_age: classDetails.min_age,
        max_age: classDetails.max_age,
        price: perUnitPrice,
        number_of_lessons: lessonCount,
        total_class_value: totalClassValue,
        total_program_price: totalClassValue,
        amount_due_now: amountDueNow,
        payment_charges_frequency: paymentFrequency,
        price_name: classDetails.fee_basis,
        payer_id: classDetails.payer_id,
        invoice_tax_value: classDetails.invoice_tax || classDetails.franchise?.invoice_tax_value,
        invoice_tax_label: classDetails.invoice_tax_label || classDetails.franchise?.invoice_tax_label,
        company_name: classDetails.franchise?.company_name,
        company_address: classDetails.franchise?.company_address,
      };

      const payload = {
        form_id: form?.id || "registration_form",
        form_data: formData,
        slug: "home",
        class_details: classData
      };

      const response = (await submitFormAction(payload)) as any;
      const subId = response.submission_id || submissionId;

      if (!response.status || !subId) {
        setErrors(prev => ({ ...prev, form: response.message || "Failed to submit registration" }));
        ev.complete("fail");
        return;
      }
      setLastSubmissionId(subId);
      // Remember this registrant's details for next time (prefill).
      rememberRegistrant();

      // 3. Initiate Payment with Backend to get client_secret
      const paymentResponse = await initiatePaymentAction({
        user_id: 1,
        gateway: "stripe",
        amount: amountDueNow,
        currency: "usd",
        email: parentInfo.email,
        registration_id: subId,
        class_id: classDetails.id,
        class_name: classDetails.group_name,
        fee_basis: classDetails.fee_basis,
        save_card: false, // Don't typically save wallet cards via standard boolean
      } as any);

      const paymentData = Array.isArray(paymentResponse.data) ? paymentResponse.data[0] : paymentResponse.data;
      const clientSecret = extractClientSecretFromPayment(paymentData);
      const stripeAccountId = extractStripeAccountFromPayment(paymentData);
      const intentId =
        paymentData?.payment_intent_id ||
        paymentData?.response?.id ||
        (clientSecret ? clientSecret.split("_secret_")[0] : null);

      if (intentId && subId) {
        sessionStorage.setItem(`payment_intent_${subId}`, intentId);
        if (clientSecret) {
          sessionStorage.setItem(`payment_${subId}`, clientSecret);
        }
      }

      if (stripeAccountId) {
        writeStripeAccountToSession(subId, stripeAccountId);
      }

      if (!clientSecret || !stripeAccountId || !stripe) {
        ev.complete("fail");
        setPaymentError("Payment configuration error: Stripe is not ready.");
        return;
      }

      // Must use the same Stripe instance that created the Elements (useStripe hook)
      const { error, paymentIntent } = await stripe.confirmCardPayment(
        clientSecret,
        { payment_method: ev.paymentMethod.id },
        { handleActions: true }
      );

      if (error) {
        ev.complete("fail");
        setPaymentError(error.message || "Payment failed");
      } else if (
        paymentIntent?.status === "succeeded" ||
        paymentIntent?.status === "processing"
      ) {
        ev.complete("success");
        await syncPaymentAndNotify(subId, paymentIntent?.id ?? intentId);
        const statusParam =
          paymentIntent.status === "processing" ? "processing" : "succeeded";
        const thankYouParams = new URLSearchParams({ redirect_status: statusParam });
        if (paymentIntent?.id) {
          thankYouParams.set("payment_intent", paymentIntent.id);
        }
        push(`/thank-you/${subId}?${thankYouParams.toString()}`);
      } else if (paymentIntent?.status === "requires_action") {
        ev.complete("success");
        setPaymentError("Additional authentication is required. Please complete payment on the next screen.");
        push(`/pay/${subId}`);
      } else {
        ev.complete("fail");
        setPaymentError("Payment could not be completed.");
      }
    } catch (error) {
      console.error("Wallet auth error:", error);
      ev.complete("fail");
      setPaymentError("An error occurred during payment processing.");
    } finally {
      setIsSubmitting(false);
    }
  };

  const handlePayNow = async (passedSubmissionId?: string) => {
    const idToUse = passedSubmissionId || submissionId;
    if (!idToUse) return;

    setIsProcessingPayment(true);
    setPaymentError(null);
    try {
      let response;
      const email = parentInfo.email;
      const isDemo = String(classDetails?.value) === "0" || !classDetails?.value;

      if (isDemo) {
        response = await setupPaymentAction({
          user_id: 1,
          gateway: "stripe",
          email: email,
          registration_id: idToUse,
          save_card: saveCard,
        });
      } else {
        response = await initiatePaymentAction({
          user_id: 1,
          gateway: "stripe",
          amount: amountDueNow,
          currency: "usd",
          email: email,
          registration_id: idToUse,
          class_id: classDetails.id,
          class_name: classDetails.group_name,
          fee_basis: classDetails.fee_basis,
          save_card: saveCard,
        } as any);
      }

      if (response.status && response.data) {
        const paymentData = Array.isArray(response.data) ? response.data[0] : response.data;
        const clientSecret = extractClientSecretFromPayment(paymentData);
        const intentId =
          paymentData?.payment_intent_id ||
          paymentData?.response?.id ||
          (clientSecret ? clientSecret.split("_secret_")[0] : null);

        const stripeAccountId = extractStripeAccountFromPayment(paymentData);

        if (intentId && idToUse) {
          sessionStorage.setItem(`payment_intent_${idToUse}`, intentId);
          if (clientSecret) {
            sessionStorage.setItem(`payment_${idToUse}`, clientSecret);
          }
          writeStripeAccountToSession(idToUse, stripeAccountId);
        }

        if (!stripeAccountId) {
          setPaymentError("Payment configuration error: Stripe connected account missing.");
          setIsProcessingPayment(false);
          return;
        }

        if (!clientSecret) {
          setPaymentError("Payment could not be started. Please try again.");
          setIsProcessingPayment(false);
          return;
        }

        if (clientSecret && stripe && elements) {
          const isSetupIntent = clientSecret.startsWith("seti_");
          let stripeError;

          const cardElement = elements.getElement("cardNumber");
          if (!cardElement) {
            setPaymentError("Payment UI error: Card element not found.");
            setIsProcessingPayment(false);
            return;
          }

          if (isSetupIntent) {
            const { error } = await stripe.confirmCardSetup(clientSecret, {
              payment_method: {
                card: cardElement,
                billing_details: { name: cardName, email: parentInfo.email },
              },
            });
            stripeError = error;
          } else {
            const { error } = await stripe.confirmCardPayment(clientSecret, {
              payment_method: {
                card: cardElement,
                billing_details: { name: cardName, email: parentInfo.email },
              },
            });
            stripeError = error;
          }

          if (stripeError) {
            setPaymentError(stripeError.message || "Payment failed");
          } else {
            await syncPaymentAndNotify(idToUse, intentId);
            const thankYouParams = new URLSearchParams({ redirect_status: "succeeded" });
            if (intentId) {
              thankYouParams.set(
                intentId.startsWith("seti_") ? "setup_intent" : "payment_intent",
                intentId
              );
            }
            push(`/thank-you/${idToUse}?${thankYouParams.toString()}`);
          }
        } else {
          push(`/pay/${idToUse}`);
        }
      } else {
        setPaymentError(formatPaymentErrorMessage(response.message));
      }
    } catch (error) {
      setPaymentError(formatPaymentErrorMessage(
        error instanceof Error ? error.message : undefined
      ));
    } finally {
      setIsProcessingPayment(false);
    }
  };

  const isFormFilled =
    parentInfo.firstName.trim() !== "" &&
    parentInfo.email.trim() !== "" &&
    parentInfo.phone.trim() !== "" &&
    childInfo.firstName.trim() !== "" &&
    childInfo.age.trim() !== "" &&
    childInfo.school.trim() !== "" &&
    agreed &&
    (paymentMethod !== "card" || (cardName.trim() !== "" && isCardComplete));

  if (!classDetails) return null;

  return (
    <section className="relative bg-transperent mt-10 py-10 px-5 xl:px-0 max-w-[1300px] mx-auto w-full registration-form">
      {/* Minimal Elegant Back Link */}
      <div className="mb-8">
        <button
          onClick={() => push("/class-registration")}
          className="inline-flex items-center gap-2 text-[#0097DC] hover:text-[#0097DC] font-medium text-[15px] transition-colors cursor-pointer group"
        >
          <ChevronLeft className="w-5 h-5 transition-transform group-hover:-translate-x-1 text-[#0097DC]" />
          <span>Back to Classes</span>
        </button>
      </div>

      <div className="max-w-[1300px] mx-auto flex flex-col-reverse md:flex-row gap-[60px] md:gap-[30px] lg:gap-[70px] justify-between">
        <div className="flex-1 w-full min-w-0 min-[768px]:max-[1024px]:max-w-[400px] max-[767px]:max-w-full registration-left-section">
          <div className="text-center mb-10">
            <h2 className="text-[30px] md:text-[30px] lg:text-[40px] xl:text-[40px] 2xl:text-[40px] leading-tight font-bold text-[#58585A] uppercase tracking-wide">
              {pageContent?.registerMainHeading || "Register For A Program"}
            </h2>
            <p className="text-[14px] md:text-[14px] lg:text-[20px] xl:text-[22px] 2xl:text-[24px] text-[#58585A] mt-2">
              {pageContent?.registerSubHeading || "Fill in the form to join the classes"}
            </p>
          </div>

          {/* 1. Parent Info */}
          <div className="border-b border-[#ddd] pb-8 mb-8">
            <h3 className="text-[20px] text-[#58585A] mb-5 font-light">
              {pageContent?.parentDetailText || (<>1. Provide <span className="font-regular">parent</span> info</>)}
            </h3>
            <div className="grid grid-cols-1 lg:grid-cols-2 gap-6 form-grid">
              <div className="flex flex-col gap-2">
                <TextInputWithValidation
                  placeholder={pageContent?.nameText || "First name"}
                  value={parentInfo.firstName}
                  onChange={(e) => setParentInfo({ ...parentInfo, firstName: e.target.value })}
                  onBlur={() => validateField("parent_first_name", parentInfo.firstName, "name")}
                  error={errors["parent_first_name"]}
                  disabled={isReadOnly}
                />
              </div>
              <div className="flex flex-col gap-2">
                <TextInputWithValidation
                  placeholder={pageContent?.lastNameText || "Last name"}
                  value={parentInfo.lastName}
                  onChange={(e) => setParentInfo({ ...parentInfo, lastName: e.target.value })}
                  onBlur={() => validateField("parent_last_name", parentInfo.lastName, "name", false)}
                  error={errors["parent_last_name"]}
                  disabled={isReadOnly}
                />
              </div>
              <div className="flex flex-col gap-2">
                <TextInputWithValidation
                  placeholder={pageContent?.emailText || "E-mail"}
                  type="email"
                  value={parentInfo.email}
                  onChange={(e) => setParentInfo({ ...parentInfo, email: e.target.value })}
                  onBlur={() => validateField("parent_email", parentInfo.email, "email")}
                  error={errors["parent_email"]}
                  disabled={isReadOnly}
                />
              </div>
              <div className="flex flex-col gap-2">
                {/* Same country-picker input the footer/contact forms already
                    use (FormRenderer routes CMS `number` fields to it), so the
                    phone field looks and behaves identically everywhere. It
                    stores "<dial> <national>" — the exact shape the prefill
                    below already supplies, unlike formatPhoneNumber which
                    reshaped a country code into a US-style "(917)" grouping. */}
                <PhoneInput
                  placeholder={pageContent?.phoneText || "Enter your phone number"}
                  value={parentInfo.phone}
                  onChange={(combined) => setParentInfo({ ...parentInfo, phone: combined })}
                  onBlur={() => validateField("parent_phone", parentInfo.phone, "phone")}
                  error={errors["parent_phone"]}
                  disabled={isReadOnly}
                />
              </div>
            </div>
          </div>

          {/* 2. Child Info */}
          <div className="border-b border-[#ddd] pb-8 mb-8">
            <h3 className="text-[20px] text-[#58585A] mb-5 font-light">
              {pageContent?.childDetailText || (<>2. Provide your <span className="font-regular">child</span> info</>)}
            </h3>
            <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
              <div className="flex flex-col gap-2">
                <TextInputWithValidation
                  placeholder={pageContent?.childFirstNameText || "First name"}
                  value={childInfo.firstName}
                  onChange={(e) => setChildInfo({ ...childInfo, firstName: e.target.value })}
                  onBlur={() => validateField("child_first_name", childInfo.firstName, "name")}
                  error={errors["child_first_name"]}
                  disabled={isReadOnly}
                />
              </div>
              <div className="flex flex-col gap-2">
                <TextInputWithValidation
                  placeholder={pageContent?.childLastNameText || "Last name"}
                  value={childInfo.lastName}
                  onChange={(e) => setChildInfo({ ...childInfo, lastName: e.target.value })}
                  onBlur={() => validateField("child_last_name", childInfo.lastName, "name", false)}
                  error={errors["child_last_name"]}
                  disabled={isReadOnly}
                />
              </div>
              <div className="flex flex-col gap-2">
                <SelectDropdown
                  placeholder={pageContent?.ageText || "Age"}
                  value={childInfo.age}
                  onChange={(val) => {
                    setChildInfo({ ...childInfo, age: val });
                    validateField("child_age", val);
                  }}
                  // Age ranges, matching the options the footer form offers.
                  options={["4-6", "7-10", "11-12", "13-18"]}
                  disabled={isReadOnly}
                />
                {errors["child_age"] && <p className="text-red-500 text-[13px] ml-4 mt-1">{errors["child_age"]}</p>}
              </div>
              <div className="flex flex-col gap-2">
                <SelectDropdown
                  placeholder={pageContent?.schoolTypeText || "School"}
                  value={childInfo.school}
                  onChange={(val) => {
                    setChildInfo({ ...childInfo, school: val });
                    validateField("child_school", val);
                  }}
                  options={["Public School", "Private School", "Home School", "Other"]}
                  disabled={isReadOnly}
                />
                {errors["child_school"] && <p className="text-red-500 text-[13px] ml-4 mt-1">{errors["child_school"]}</p>}
              </div>
            </div>
          </div>

          <div className="mt-1">
            {String(classDetails?.payer_id) !== "2" && (
            <>
            {/* 3. Program Summary */}
            <div className="border-b border-[#ddd] pb-8 mb-8 mt-5">
              <h3 className="text-[18px] md:text-[20px] text-[#58585A] font-light">
                3. The chosen program includes {lessonCount} lessons with {paymentFrequencyLabel.toLowerCase()} payments of ${formatAmount(perUnitPrice)}.
              </h3>
            </div>

            {/* 4. Coupon */}
            <div className="border-b border-[#ddd] pb-8 mb-8">
              <h3 className="text-[20px] text-[#58585A] font-light mb-5">
                {pageContent?.couponSectionTitleText?.replace(/^3\./, '4.') || "4. Have a coupon?"}
              </h3>

              {/* Opt-in: only reveal the code field when the user has a coupon */}
              {!isReadOnly && (
                <label className="flex items-center gap-2 cursor-pointer mb-4 select-none w-fit">
                  <input
                    type="checkbox"
                    checked={showCoupon}
                    onChange={(e) => {
                      const checked = e.target.checked;
                      setShowCoupon(checked);
                      // Clearing on uncheck so a hidden coupon can't stay applied.
                      if (!checked) {
                        setCoupon("");
                        setCouponData(null);
                        setCouponError("");
                      }
                    }}
                    className="w-[20px] h-[20px] accent-[#0097dc] cursor-pointer"
                  />
                  <span className="text-[16px] text-[#58585A]">
                    {pageContent?.couponToggleText || "Do you have a coupon?"}
                  </span>
                </label>
              )}

              {showCoupon && (
                <div className="max-w-[320px]">
                  <div className="flex flex-col gap-2">
                    <input
                      type="text"
                      placeholder={pageContent?.couponInputPlaceholderText || "Enter code"}
                      value={coupon}
                      onChange={(e) => setCoupon(e.target.value.toUpperCase())}
                      className="w-full h-[50px] rounded-full border border-[#58585A] bg-transparent px-6 outline-none text-[16px]"
                    />
                    {couponError && <p className="text-red-500 text-sm pl-4">{couponError}</p>}
                    {couponData && <p className="text-green-500 text-sm pl-4">Coupon applied! Save ${getDiscountAmount()}</p>}
                  </div>
                  <button
                    disabled={!coupon.trim() || isVerifyingCoupon || !!couponData}
                    onClick={handleApplyCoupon}
                    className={`w-full h-[50px] rounded-full mt-3 text-[16px] transition-all duration-300
                  ${coupon.trim() && !isVerifyingCoupon && !couponData
                        ? "bg-[#0097dc] text-white cursor-pointer"
                        : "bg-[#d9d9d9] text-[#999] cursor-not-allowed"
                      }`}
                  >
                    {isVerifyingCoupon ? "Applying..." : couponData ? "Applied" : (pageContent?.couponApplyButtonText || "Apply")}
                  </button>
                </div>
              )}
            </div>

            {/* 5. Payment Methods */}
            <div>
              <h3 className="text-[20px] text-[#58585A] font-light mb-5">
                {pageContent?.paymentSectionTitleText?.replace(/^4\./, '5.') || "5. Choose payment method"}
              </h3>
              <div className="flex flex-col gap-5 payment-box">
                {String(classDetails?.payer_id) !== "2" && (
                  <>
                    {/* Switcher: all payment methods grouped at the top */}
                    <div className="flex flex-wrap items-center gap-x-6 gap-y-3">
                      <label className="flex items-center gap-3 text-[20px] text-[#58585A] font-light cursor-pointer">
                        <input type="radio" name="payment" className="w-5 h-5" checked={paymentMethod === "card"} onChange={() => setPaymentMethod("card")} />
                        {pageContent?.paymentByCardText || "By card"}
                      </label>

                      {/* ONLY show Apple Pay if available */}
                      {walletAvailability.applePay && (
                        <label className="flex items-center gap-3 text-[20px] text-[#58585A] font-light cursor-pointer">
                          <input type="radio" name="payment" className="w-5 h-5" checked={paymentMethod === "apple"} onChange={() => setPaymentMethod("apple")} />
                          {/* Official Apple Pay acceptance mark (SVG) — sharp at any
                              density, unlike the 138x48 PNG it replaces.

                              NOTE: this is still the BORDERED variant, because the
                              Marketing kit download only contained the mark, not
                              the logo. Its frame costs ~40% of the height, so at
                              Google's 23px the glyph inside would be tiny; 30px
                              keeps it legible while staying close enough that the
                              two do not look mismatched. Swap in Apple_Pay_Logo_*
                              when available and drop this to h-[23px] to match. */}
                          <Image src={withCDN("/class-registration/Apple_Pay_Mark_RGB_041619.svg")} alt="Apple Pay" width={166} height={106} className="h-[30px] w-auto" priority={true} />
                        </label>
                      )}

                      {walletAvailability.googlePay && (
                        <label className="flex items-center gap-3 text-[20px] text-[#58585A] font-light cursor-pointer">
                          <input type="radio" name="payment" className="w-5 h-5" checked={paymentMethod === "google"} onChange={() => setPaymentMethod("google")} />
                          {/* Official Google Pay wordmark, LIGHT-background variant.
                              Google names these after the button theme, not the ink:
                              dark_gpay is for the black button and its "Pay" is
                              #FFF, so on this white row only the coloured G showed.
                              This one uses #5F6368 grey and stays legible.

                              A viewBox was added (Google ships neither variant with
                              one), so w-auto can derive the 41:17 ratio and it
                              scales cleanly. At 2.41 that ratio matches the 128x52
                              PNG this replaces, so the row keeps its original
                              proportions — now vector, so sharp at any density. */}
                          <Image src={withCDN("/class-registration/gpay-wordmark-light.svg")} alt="Google Pay" width={41} height={17} className="h-[23px] w-auto" priority={true} />
                        </label>
                      )}

                      {walletAvailability.link && (
                        <label className="flex items-center gap-3 text-[20px] text-[#58585A] font-light cursor-pointer">
                          <input type="radio" name="payment" className="w-5 h-5" checked={paymentMethod === "link"} onChange={() => setPaymentMethod("link")} />
                          <span className="inline-flex items-center gap-2 bg-[#33ddb3] text-black text-[14px] font-semibold px-3 py-1 rounded-md">Link</span>
                        </label>
                      )}
                    </div>

                    {/* Selected method's details, shown below the switcher */}
                    {paymentMethod === "card" && (
                      <StripePaymentFields
                        cardName={cardName}
                        setCardName={setCardName}
                        saveCard={saveCard}
                        setSaveCard={setSaveCard}
                        error={paymentError}
                        onCardChange={(complete) => setIsCardComplete(complete)}
                      />
                    )}

                    {paymentMethod === "apple" && walletAvailability.applePay && (
                      <StripeWalletFields
                        amount={amountDueNow}
                        label="Class Registration"
                        onPaymentAuth={handleWalletPaymentAuth}
                      />
                    )}

                    {paymentMethod === "google" && walletAvailability.googlePay && (
                      <StripeWalletFields
                        amount={amountDueNow}
                        label="Class Registration"
                        onPaymentAuth={handleWalletPaymentAuth}
                      />
                    )}

                    {paymentMethod === "link" && walletAvailability.link && (
                      <StripeWalletFields
                        amount={amountDueNow}
                        label="Class Registration"
                        onPaymentAuth={handleWalletPaymentAuth}
                      />
                    )}
                  </>
                )}

                {String(classDetails?.payer_id) === "2" && (
                  <label className="flex items-center gap-3 text-[20px] text-[#58585A] font-light">
                    <input type="radio" name="payment" className="w-5 h-5" checked={paymentMethod === "later"} onChange={() => setPaymentMethod("later")} />
                    {pageContent?.paymentPayLaterText || "Pay later (we will contact you for more details)"}
                  </label>
                )}
              </div>
            </div>
            </>
            )}
          </div>

          {errors.form && (
            <p className="text-red-500 text-[16px] mt-4 text-center font-medium">{errors.form}</p>
          )}
          {paymentError && paymentMethod !== "card" && (
            <p className="text-red-500 text-[16px] mt-4 text-center font-medium">{paymentError}</p>
          )}

          {/* Policy — shown ABOVE the Register & Pay button */}
          <div
            // items-start (not items-center): on mobile the label wraps to two
            // lines, and centering would float the box between them instead of
            // lining it up with the first line.
            //
            // Horizontal alignment depends on whether there is a payment block
            // to line up with. payer_id "2" hides sections 4 and 5 entirely
            // (see the guard above), so there is no "Save my card details"
            // checkbox to share a left edge with and the row was left stranded
            // against the edge — centred it reads as belonging to the button.
            // With payment shown, justify-start + px-1 keeps the two checkboxes
            // on one left edge, as before.
            //
            // Only from md up: on mobile the label wraps to two lines and
            // centring would ragged-edge it, so it stays left there.
            className={`flex items-start justify-start px-1 text-[16px] mt-[20px] mb-2 cursor-pointer ${
              String(classDetails?.payer_id) === "2" ? "policy-row-centered" : ""
            }`}
            onClick={() => {
              setAgreed(!agreed);
              if (!agreed && errors.policy) {
                setErrors(prev => { const newErrors = { ...prev }; delete newErrors.policy; return newErrors; });
              }
            }}
          >
            {/* mt-[2px] optically centres the box against the first line of
                the 16px/1.5 label rather than its cap height. */}
            <div className={`w-[20px] h-[20px] md:w-[25px] md:h-[25px] mt-[2px] border ${errors.policy ? 'border-red-500' : 'border-[#58585A]'} rounded-[6px] mr-[10px] flex-shrink-0 flex items-center justify-center transition-all duration-200`}>
              <div className={`w-[12px] h-[12px] md:w-[15px] md:h-[15px] rounded-[4px] transition-all duration-200 ${agreed ? "bg-[#0097DC]" : "bg-transparent"}`} />
            </div>
            <span className="text-[#58585A] text-[16px] font-light text-left leading-[24px]">
              {pageContent?.policyAgreementPrefixText || "I agree with the"}{" "}
              <a
                className="text-[#0097DC] cursor-pointer hover:underline"
                onClick={(e) => { e.stopPropagation(); openPrivacyPolicy(); }}
              >
                {pageContent?.privacyPolicyLinkText || "Privacy Policy"}
              </a>
              {" and "}
              <a
                className="text-[#0097DC] cursor-pointer hover:underline"
                onClick={(e) => { e.stopPropagation(); openTermsOfUse(); }}
              >
                {pageContent?.termsOfUseLinkText || "Terms of Use"}
              </a>
            </span>
          </div>
          {errors.policy && (
            <p className="text-red-500 text-[14px] mt-1 mb-2 text-center">{errors.policy}</p>
          )}

          <button
            onClick={handleSubmit}
            disabled={isSubmitting || isProcessingPayment || !isFormFilled}
            className="mt-4 h-[50px] w-full md:w-[70%] mx-auto tracking-[1px] rounded-full bg-[#0097DC] text-[16px] md:text-[16px] font-light text-white outline-none transition-all hover:bg-[#0097DC] hover:shadow-[10px_10px_14px_#0000000D] active:shadow-[10px_10px_14px_#0000000D]  active:bg-[#0084C1] disabled:bg-[#e0e0e0] disabled:text-[#58585A] flex items-center justify-center max-[375px]:text-[12px] cursor-pointer md:gap-[6px] submit-btn"
          >
            {isSubmitting || isProcessingPayment ? (
              <Loader2 className="w-5 h-5 mr-2 animate-spin shrink-0" aria-hidden />
            ) : (
              <Image
                src={withCDN("/gear.png")}
                alt="Gear"
                width={20}
                height={20}
                className="w-[20px] h-[20px] mr-2 shrink-0"
                priority={true}
              />
            )}

            {isSubmitting || isProcessingPayment ? (
              isProcessingPayment ? "Verifying payment…" : "Processing…"
            ) : paymentMethod === "later" ? (
              pageContent?.ctaPayLaterButtonText || "Register and pay later") : (
              <>
                Register and pay ${formatAmount(displayPaymentAmount)}

                {paymentPlans?.[0]?.due_date && (
                  <span className="hidden md:inline">
                    {" "}
                    for{" "}
                    {new Date(paymentPlans[0].due_date).toLocaleDateString("en-GB", { day: "2-digit", month: "short", year: "numeric" })}
                  </span>
                )}
              </>
            )}
          </button>
        </div>

        {/*===========SIDEBAR=============*/}
        {classDetails && (
          <RegistrationSidebar
            classDetails={classDetails}
            paymentPlans={paymentPlans}
            finalPrice={amountDueNow}
            originalPrice={perUnitPrice}
            totalProgramPrice={totalClassValue}
            pageContent={pageContent}
            displayPaymentAmount={amountDueNow}
          />
        )}
      </div>

      <PrivacyPolicyModal
        isOpen={isPrivacyOpen}
        onClose={() => setIsPrivacyOpen(false)}
        heading={privacyContent?.heading}
        effectiveDate={privacyContent?.effectiveDate}
        content={privacyContent?.content}
        isLoading={isPrivacyLoading}
        linkLabel={pageContent?.privacyPolicyLinkText || "Privacy Policy"}
      />

      <PrivacyPolicyModal
        isOpen={isTermsOpen}
        onClose={() => setIsTermsOpen(false)}
        heading={termsContent?.heading}
        effectiveDate={termsContent?.effectiveDate}
        content={termsContent?.content}
        isLoading={isTermsLoading}
        linkLabel={pageContent?.termsOfUseLinkText || "Terms of Use"}
      />
    </section>
  );
}