"use client";

import Link from "next/link";
import {
  FormEvent,
  Suspense,
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
  type ReactNode,
} from "react";
import { useSearchParams } from "next/navigation";
import { ArrowLeft, ArrowRight, Banknote, CheckCircle2, CreditCard, Loader2 } from "lucide-react";
import { ServiceFlowHero } from "@/app/services/ServiceFlowHero";
import { AddressLocationMap } from "@/components/AddressLocationMap";
import { apiBaseUrl, apiHeaders, apiPath } from "@/lib/api-url";
import { useUserLocation } from "@/lib/location-context";
import { getUserAuthToken, useUserAuth } from "@/lib/user-auth";
import { routePath } from "@/lib/route-url";
import type {
  VehiclePackage,
  VehiclePackageModel,
} from "@/app/vehicle-packages/[vehicleType]/[manufacturerSlug]/[modelId]/VehiclePackagesClient";

type AccountAddress = {
  id: number;
  type: string;
  label: string;
  houseNo: string | null;
  street: string | null;
  locality: string | null;
  landmark: string | null;
  address: string;
  city: string | null;
  state: string | null;
  pincode: string | null;
  latitude: number | null;
  longitude: number | null;
  isDefault: boolean;
};

type AddressDraft = {
  type: string;
  houseNo: string;
  street: string;
  locality: string;
  city: string;
  state: string;
  pincode: string;
  landmark: string;
  latitude: number | null;
  longitude: number | null;
};

type ReverseLocationResponse = {
  address?: Record<string, string | undefined>;
  displayName?: string | null;
  resolvedName?: string | null;
};

type CheckoutStep = "address" | "payment" | "success";
type PaymentMode = "cash_after_service" | "online_razorpay";

type AccountSummaryResponse = {
  addresses: AccountAddress[];
};

type VehiclePackagesResponse = {
  model: VehiclePackageModel | null;
  packages?: VehiclePackage[];
};

type OrderResponse = {
  order: {
    id: number;
    orderNumber: string;
    packageName: string;
    modelName: string;
  };
  payment?: {
    provider: "razorpay";
    keyId: string;
    orderId: string;
    amount: number;
    currency: string;
  } | null;
};

type RazorpaySuccessResponse = {
  razorpay_order_id: string;
  razorpay_payment_id: string;
  razorpay_signature: string;
};

type RazorpayCheckoutOptions = {
  key: string;
  amount: number;
  currency: string;
  name: string;
  description: string;
  order_id: string;
  prefill?: {
    name?: string;
    email?: string;
    contact?: string;
  };
  notes?: Record<string, string>;
  theme?: {
    color?: string;
  };
  handler: (response: RazorpaySuccessResponse) => void;
  modal?: {
    ondismiss?: () => void;
  };
};

declare global {
  interface Window {
    Razorpay?: new (options: RazorpayCheckoutOptions) => {
      open: () => void;
      on: (
        event: string,
        handler: (response: { error?: { description?: string } }) => void,
      ) => void;
    };
  }
}

const emptyAddressDraft: AddressDraft = {
  type: "",
  houseNo: "",
  street: "",
  locality: "",
  city: "",
  state: "",
  pincode: "",
  landmark: "",
  latitude: null,
  longitude: null,
};

export type CheckoutParams = {
  serviceSlug: string;
  packageType: string;
  packageId?: number;
  packageSlug?: string;
  manufacturerSlug: string;
  modelSlug: string;
  vehicleType: "car" | "bike";
};

export default function CheckoutPage() {
  return (
    <Suspense fallback={<CheckoutLoading />}>
      <CheckoutQueryPage />
    </Suspense>
  );
}

function CheckoutQueryPage() {
  const searchParams = useSearchParams();

  return (
    <CheckoutFlow
      checkoutParams={{
        serviceSlug: searchParams.get("serviceSlug") ?? "",
        packageType: searchParams.get("packageType") ?? "service_package",
        packageId: Number(searchParams.get("packageId") ?? 0) || undefined,
        packageSlug: searchParams.get("packageSlug") ?? undefined,
        manufacturerSlug: searchParams.get("manufacturerSlug") ?? "",
        modelSlug: searchParams.get("modelSlug") ?? "",
        vehicleType: searchParams.get("vehicleType") === "bike" ? "bike" : "car",
      }}
    />
  );
}

export function CheckoutFlow({ checkoutParams }: { checkoutParams: CheckoutParams }) {
  const { user, openAuthModal } = useUserAuth();
  const { location } = useUserLocation();
  const [step, setStep] = useState<CheckoutStep>("address");
  const [addressTab, setAddressTab] = useState<"saved" | "new">("saved");
  const [addresses, setAddresses] = useState<AccountAddress[]>([]);
  const [selectedAddressId, setSelectedAddressId] = useState<number | null>(null);
  const [model, setModel] = useState<VehiclePackageModel | null>(null);
  const [servicePackage, setServicePackage] = useState<VehiclePackage | null>(null);
  const [orderNumber, setOrderNumber] = useState("");
  const [isLoading, setIsLoading] = useState(true);
  const [isSaving, setIsSaving] = useState(false);
  const [errorMessage, setErrorMessage] = useState("");
  const [selectedPaymentMode, setSelectedPaymentMode] = useState<PaymentMode>("cash_after_service");
  const loadRequestRef = useRef(0);

  const {
    serviceSlug,
    packageType,
    packageId,
    packageSlug = "",
    manufacturerSlug,
    modelSlug,
    vehicleType,
  } = checkoutParams;
  const selectedAddress = addresses.find((address) => address.id === selectedAddressId) ?? null;
  const price = getPackagePrice(servicePackage);

  const backHref = useMemo(() => {
    if (!serviceSlug || !manufacturerSlug || !modelSlug) {
      return routePath("/services");
    }

    return routePath(
      `/services/${serviceSlug}/${encodeURIComponent(manufacturerSlug)}/${encodeURIComponent(
        modelSlug,
      )}`,
    );
  }, [manufacturerSlug, modelSlug, serviceSlug]);

  async function accountRequest<T>(path: string, init: RequestInit = {}) {
    const token = getUserAuthToken();

    if (!token) {
      throw new Error("Login required");
    }

    const response = await fetch(`${apiBaseUrl}${apiPath(path)}`, {
      ...init,
      headers: apiHeaders({
        "Content-Type": "application/json",
        Authorization: `Bearer ${token}`,
        ...(init.headers ?? {}),
      }),
    });
    const data = (await response.json().catch(() => ({}))) as T & { error?: string };

    if (!response.ok) {
      throw new Error(data.error ?? "Request failed");
    }

    return data;
  }

  async function loadCheckout() {
    const requestId = loadRequestRef.current + 1;
    loadRequestRef.current = requestId;
    setIsLoading(true);
    setErrorMessage("");

    try {
      const packageData = await fetch(
        apiPath(
          `/api/vehicle-packages?manufacturerSlug=${encodeURIComponent(
            manufacturerSlug,
          )}&modelSlug=${encodeURIComponent(modelSlug)}&serviceSlug=${encodeURIComponent(
            serviceSlug,
          )}&vehicleType=${encodeURIComponent(vehicleType)}&packageType=${encodeURIComponent(packageType)}${
            location?.id ? `&locationId=${location.id}` : ""
          }`,
        ),
      ).then(async (response) => {
        const data = (await response.json()) as VehiclePackagesResponse & { error?: string };

        if (!response.ok) {
          throw new Error(data.error ?? "Could not load package");
        }

        return data;
      });
      const matchedPackage = (packageData.packages ?? []).find((item) =>
        packageId ? item.id === packageId : item.slug === packageSlug,
      );

      if (!packageData.model || !matchedPackage) {
        throw new Error("Package not found");
      }

      if (loadRequestRef.current !== requestId) {
        return;
      }

      setModel(packageData.model);
      setServicePackage(matchedPackage);

      if (!getUserAuthToken()) {
        openAuthModal();
        return;
      }

      if (user && (!user.email || !user.name || user.name === "User")) {
        openAuthModal();
        return;
      }

      const accountData = await accountRequest<AccountSummaryResponse>("/api/account/summary");

      if (loadRequestRef.current !== requestId) {
        return;
      }

      setAddresses(accountData.addresses);
      setSelectedAddressId(
        accountData.addresses.find((address) => address.isDefault)?.id ??
          accountData.addresses[0]?.id ??
          null,
      );
    } catch (error) {
      if (loadRequestRef.current === requestId) {
        setErrorMessage(error instanceof Error ? error.message : "Could not load checkout");
      }
    } finally {
      if (loadRequestRef.current === requestId) {
        setIsLoading(false);
      }
    }
  }

  useEffect(() => {
    loadCheckout();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [
    manufacturerSlug,
    modelSlug,
    packageId,
    packageSlug,
    packageType,
    serviceSlug,
    location?.id,
    user?.id,
  ]);

  async function saveAddress(event: FormEvent<HTMLFormElement>): Promise<boolean> {
    event.preventDefault();
    const form = event.currentTarget;
    setIsSaving(true);
    setErrorMessage("");

    const formData = new FormData(form);

    try {
      const data = await accountRequest<{ address: AccountAddress }>("/api/account/addresses", {
        method: "POST",
        body: JSON.stringify({
          type: String(formData.get("type") ?? ""),
          houseNo: String(formData.get("houseNo") ?? ""),
          street: String(formData.get("street") ?? ""),
          locality: String(formData.get("locality") ?? ""),
          city: String(formData.get("city") ?? ""),
          state: String(formData.get("state") ?? ""),
          pincode: String(formData.get("pincode") ?? ""),
          landmark: String(formData.get("landmark") ?? ""),
          latitude: formData.get("latitude") ? Number(formData.get("latitude")) : null,
          longitude: formData.get("longitude") ? Number(formData.get("longitude")) : null,
          isDefault: formData.get("isDefault") === "on",
        }),
      });
      const accountData = await accountRequest<AccountSummaryResponse>("/api/account/summary");
      setAddresses(accountData.addresses);
      setSelectedAddressId(data.address.id);
      setAddressTab("saved");
      form.reset();
      return true;
    } catch (error) {
      setErrorMessage(error instanceof Error ? error.message : "Could not save address");
      return false;
    } finally {
      setIsSaving(false);
    }
  }

  async function verifyRazorpayPayment(orderId: number, response: RazorpaySuccessResponse) {
    return accountRequest<OrderResponse>("/api/account/orders/razorpay/verify", {
      method: "POST",
      body: JSON.stringify({
        orderId,
        razorpayOrderId: response.razorpay_order_id,
        razorpayPaymentId: response.razorpay_payment_id,
        razorpaySignature: response.razorpay_signature,
      }),
    });
  }

  async function markRazorpayPaymentFailed(
    orderId: number,
    razorpayOrderId: string,
    reason: string,
  ) {
    await accountRequest<{ ok: boolean }>("/api/account/orders/razorpay/failed", {
      method: "POST",
      body: JSON.stringify({
        orderId,
        razorpayOrderId,
        reason,
      }),
    });
  }

  async function openRazorpayPayment(data: OrderResponse) {
    if (!data.payment || data.payment.provider !== "razorpay") {
      throw new Error("Razorpay payment was not created for this order");
    }
    const payment = data.payment;

    const isLoaded = await loadRazorpayCheckoutScript();
    const RazorpayCheckout = window.Razorpay;

    if (!isLoaded || !RazorpayCheckout) {
      throw new Error("Could not load Razorpay checkout. Please check your connection.");
    }

    await new Promise<void>((resolve, reject) => {
      let isSettled = false;

      const settle = (callback: () => void) => {
        if (isSettled) {
          return;
        }
        isSettled = true;
        callback();
      };

      const checkout = new RazorpayCheckout({
        key: payment.keyId,
        amount: payment.amount,
        currency: payment.currency,
        name: "Ride N Revive",
        description: `${servicePackage?.name ?? "Service booking"} - ${data.order.orderNumber}`,
        order_id: payment.orderId,
        prefill: {
          name: user?.name && user.name !== "User" ? user.name : undefined,
          email: user?.email ?? undefined,
          contact: user?.mobile,
        },
        notes: {
          orderNumber: data.order.orderNumber,
        },
        theme: {
          color: "#dc2626",
        },
        handler: (response) => {
          verifyRazorpayPayment(data.order.id, response)
            .then((verifiedData) => {
              setOrderNumber(verifiedData.order.orderNumber);
              setStep("success");
              settle(resolve);
            })
            .catch((error: unknown) => {
              settle(() =>
                reject(error instanceof Error ? error : new Error("Payment verification failed")),
              );
            });
        },
        modal: {
          ondismiss: () => {
            settle(() => reject(new Error("Payment was cancelled before completion")));
          },
        },
      });

      checkout.on("payment.failed", (response) => {
        const reason = response.error?.description ?? "Razorpay payment failed";
        markRazorpayPaymentFailed(data.order.id, payment.orderId, reason)
          .catch((error: unknown) => {
            console.error("Could not mark Razorpay payment as failed", error);
          })
          .finally(() => {
            settle(() => reject(new Error(reason)));
          });
      });
      checkout.open();
    });
  }

  async function placeOrder(paymentMode: PaymentMode) {
    if (!servicePackage || !selectedAddressId) {
      setErrorMessage("Select or add an address first");
      return;
    }

    setIsSaving(true);
    setErrorMessage("");

    try {
      const data = await accountRequest<OrderResponse>("/api/account/orders", {
        method: "POST",
        body: JSON.stringify({
          serviceSlug,
          packageType,
          packageId: servicePackage.id,
          manufacturerSlug,
          modelSlug,
          vehicleType,
          locationId: location?.id ?? null,
          addressId: selectedAddressId,
          paymentMode,
        }),
      });

      if (paymentMode === "online_razorpay") {
        await openRazorpayPayment(data);
        return;
      }

      setOrderNumber(data.order.orderNumber);
      setStep("success");
    } catch (error) {
      setErrorMessage(error instanceof Error ? error.message : "Could not place order");
    } finally {
      setIsSaving(false);
    }
  }

  return (
    <>
      <ServiceFlowHero
        currentPage="Checkout"
        eyebrow="Secure booking"
        title={servicePackage?.name ? `Book ${servicePackage.name}` : "Complete your booking"}
        lead={
          model
            ? `${[model.manufacturerName, model.name].filter(Boolean).join(" ")} service booking with address selection and secure payment options.`
            : "Choose your address, confirm payment mode, and place your service order."
        }
        backHref={backHref}
        backLabel="Back to packages"
      />

      <main className="min-h-screen bg-slate-50 font-['Space_Grotesk']">
        <section className="mx-auto max-w-7xl px-4 py-12 md:py-16">
          <div className="mb-5 grid gap-5 rounded-xl border border-border bg-white p-5 shadow-sm lg:grid-cols-[minmax(0,1fr)_360px] lg:items-center">
            <div>
              <p className="inline-flex rounded-md bg-primary/10 px-3 py-1 text-xs font-black uppercase tracking-[0.14em] text-primary">
                Checkout
              </p>
              <h2 className="mt-3 max-w-3xl text-2xl font-black tracking-tight text-foreground md:text-3xl">
                Confirm your service details.
              </h2>
              <p className="mt-2 max-w-2xl text-sm font-semibold leading-7 text-muted-foreground">
                Select a saved address or add a new one, then choose cash after service or online
                payment to place the order.
              </p>
            </div>

            <div className="rounded-xl border border-border bg-slate-50 p-4">
              <div className="min-w-0">
                <p className="text-[10px] font-black uppercase tracking-[0.18em] text-muted-foreground">
                  Selected package
                </p>
                <p className="mt-2 line-clamp-2 text-lg font-black leading-tight text-foreground">
                  {servicePackage?.name ?? "Loading package"}
                </p>
              </div>

              <div className="mt-3 grid grid-cols-[minmax(0,1fr)_88px] gap-2">
                <div className="min-w-0 rounded-lg border border-primary/15 bg-white px-3 py-3 shadow-sm">
                  <CheckoutPriceBlock servicePackage={servicePackage} compact />
                </div>
                <div className="grid min-h-[64px] place-items-center rounded-lg border border-border bg-white px-2 py-3 text-center shadow-sm">
                  <div>
                    <p className="text-[9px] font-black uppercase tracking-[0.14em] text-muted-foreground">
                      Time
                    </p>
                    <p className="mt-1 text-xs font-black leading-tight text-slate-800">
                      {servicePackage?.estimatedDuration ?? "-"}
                    </p>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <div className="grid overflow-hidden rounded-lg border border-border bg-white shadow-sm lg:grid-cols-[minmax(0,1fr)_360px]">
            <div className="p-5 sm:p-6">
              <CheckoutSteps activeStep={step} />

              {errorMessage ? (
                <p className="mt-4 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm font-bold text-destructive">
                  {errorMessage}
                </p>
              ) : null}

              {isLoading ? (
                <div className="grid min-h-72 place-items-center">
                  <Loader2 className="h-6 w-6 animate-spin text-primary" />
                </div>
              ) : null}

              {!isLoading && step === "address" ? (
                <section className="mt-5 overflow-hidden rounded-lg border border-border bg-white">
                  <div className="flex gap-2 border-b border-border bg-slate-50 p-2">
                    {(["saved", "new"] as const).map((tab) => (
                      <button
                        key={tab}
                        type="button"
                        onClick={() => setAddressTab(tab)}
                        className={`h-10 rounded-md px-4 text-sm font-black transition ${
                          addressTab === tab
                            ? "bg-primary text-primary-foreground"
                            : "text-muted-foreground hover:bg-white hover:text-foreground"
                        }`}
                      >
                        {tab === "saved" ? "Saved addresses" : "New address"}
                      </button>
                    ))}
                  </div>

                  {addressTab === "saved" ? (
                    <div className="grid gap-3 p-4">
                      {addresses.length === 0 ? (
                        <p className="rounded-md border border-dashed border-border px-4 py-8 text-center text-sm font-bold text-muted-foreground">
                          No saved addresses yet. Add a new address.
                        </p>
                      ) : null}
                      {addresses.map((address) => (
                        <button
                          key={address.id}
                          type="button"
                          onClick={() => setSelectedAddressId(address.id)}
                          className={`rounded-md border p-4 text-left transition ${
                            selectedAddressId === address.id
                              ? "border-primary bg-primary/5 ring-2 ring-primary/10"
                              : "border-border hover:border-primary/30"
                          }`}
                        >
                          <div className="flex items-center justify-between gap-3">
                            <p className="font-black">{formatAddressTitle(address)}</p>
                            {address.isDefault ? (
                              <span className="rounded-md bg-primary/10 px-2 py-1 text-[10px] font-black uppercase tracking-[0.12em] text-primary">
                                Default
                              </span>
                            ) : null}
                          </div>
                          <p className="mt-2 text-sm font-bold leading-6 text-muted-foreground">
                            {formatAddressLine(address)}
                          </p>
                        </button>
                      ))}
                    </div>
                  ) : (
                    <CheckoutAddressForm isSaving={isSaving} onSave={saveAddress} />
                  )}
                </section>
              ) : null}

              {!isLoading && step === "payment" ? (
                <section className="mt-5 rounded-lg border border-border bg-white p-4">
                  <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
                    <div>
                      <h2 className="font-black text-foreground">Payment mode</h2>
                      <p className="mt-1 text-sm font-bold text-muted-foreground">
                        Choose how you want to pay for this service booking.
                      </p>
                    </div>
                    <button
                      type="button"
                      onClick={() => {
                        setErrorMessage("");
                        setStep("address");
                      }}
                      disabled={isSaving}
                      className="inline-flex h-10 items-center justify-center gap-2 rounded-md border border-border bg-white px-3 text-xs font-black text-muted-foreground transition hover:bg-slate-100 hover:text-foreground disabled:opacity-60"
                    >
                      <ArrowLeft className="h-4 w-4" />
                      Back to address
                    </button>
                  </div>
                  <div className="mt-4 grid gap-3">
                    <PaymentModeButton
                      mode="cash_after_service"
                      selectedMode={selectedPaymentMode}
                      title="Cash after service"
                      description="Pay the team after the service is completed."
                      icon={<Banknote className="h-5 w-5" />}
                      onSelect={setSelectedPaymentMode}
                    />
                    <PaymentModeButton
                      mode="online_razorpay"
                      selectedMode={selectedPaymentMode}
                      title="Online payment"
                      description="Pay securely now using Razorpay cards, UPI, netbanking, or wallets."
                      icon={<CreditCard className="h-5 w-5" />}
                      onSelect={setSelectedPaymentMode}
                    />
                  </div>
                  <button
                    type="button"
                    onClick={() => placeOrder(selectedPaymentMode)}
                    disabled={isSaving}
                    className="mt-4 inline-flex h-12 w-full items-center justify-center gap-2 rounded-md bg-primary px-4 text-sm font-black text-primary-foreground transition hover:bg-primary/90 disabled:opacity-60"
                  >
                    {isSaving ? <Loader2 className="h-4 w-4 animate-spin" /> : null}
                    {selectedPaymentMode === "online_razorpay"
                      ? `Pay ${price > 0 ? formatCurrency(price) : "online"}`
                      : "Place order"}
                    {!isSaving ? <ArrowRight className="h-4 w-4" /> : null}
                  </button>
                </section>
              ) : null}

              {!isLoading && step === "success" ? (
                <section className="mt-5 rounded-lg border border-emerald-200 bg-emerald-50 p-8 text-center">
                  <div className="mx-auto grid h-14 w-14 place-items-center rounded-full bg-emerald-600 text-white">
                    <CheckCircle2 className="h-7 w-7" />
                  </div>
                  <h2 className="mt-4 text-3xl font-black text-foreground">Order placed</h2>
                  <p className="mt-2 text-sm font-bold text-muted-foreground">
                    Your order {orderNumber} has been saved.
                  </p>
                  <Link
                    href={routePath("/account")}
                    className="mt-5 inline-flex h-11 items-center justify-center rounded-md bg-primary px-5 text-sm font-black text-primary-foreground"
                  >
                    View account
                  </Link>
                </section>
              ) : null}
            </div>

            <aside className="border-t border-border bg-slate-50 p-5 lg:border-l lg:border-t-0">
              <h2 className="text-sm font-black uppercase tracking-[0.14em] text-muted-foreground">
                Order summary
              </h2>
              <div className="mt-4 space-y-3 rounded-lg border border-border bg-white p-4">
                <SummaryRow label="Package" value={servicePackage?.name ?? "-"} />
                <SummaryRow label="Duration" value={servicePackage?.estimatedDuration ?? "-"} />
                <SummaryRow
                  label="Vehicle"
                  value={[model?.manufacturerName, model?.name].filter(Boolean).join(" ") || "-"}
                />
                <SummaryRow
                  label="Amount"
                  value={price > 0 ? formatCurrency(price) : "To confirm"}
                  content={<CheckoutPriceBlock servicePackage={servicePackage} compact />}
                />
                {selectedAddress ? (
                  <div className="border-t border-border pt-3">
                    <p className="text-xs font-black uppercase tracking-[0.14em] text-muted-foreground">
                      Address
                    </p>
                    <p className="mt-1 text-sm font-bold leading-6 text-foreground">
                      {formatAddressLine(selectedAddress)}
                    </p>
                  </div>
                ) : null}
              </div>

              {step === "address" ? (
                <button
                  type="button"
                  onClick={() => {
                    if (!selectedAddressId) {
                      setErrorMessage("Select or add an address first");
                      return;
                    }
                    setErrorMessage("");
                    setStep("payment");
                  }}
                  disabled={!selectedAddressId || isLoading}
                  className="mt-4 inline-flex h-11 w-full items-center justify-center gap-2 rounded-md bg-primary px-4 text-sm font-black text-primary-foreground disabled:opacity-50"
                >
                  Continue to payment
                  <ArrowRight className="h-4 w-4" />
                </button>
              ) : null}
            </aside>
          </div>
        </section>
      </main>
    </>
  );
}

function CheckoutLoading() {
  return (
    <main className="min-h-screen bg-slate-50 font-['Space_Grotesk']">
      <section className="bg-primary text-primary-foreground">
        <div className="mx-auto max-w-7xl px-4 pb-8 pt-24 2xl:pb-10 2xl:pt-28">
          <p className="text-xs font-black uppercase tracking-[0.18em] text-primary-foreground/75">
            Secure booking
          </p>
          <h1 className="mt-2 max-w-3xl font-display text-3xl font-bold leading-tight tracking-tight sm:text-4xl 2xl:text-5xl">
            Loading checkout
          </h1>
        </div>
      </section>
      <section className="mx-auto grid min-h-96 max-w-7xl place-items-center px-4 py-12">
        <div className="grid min-h-72 w-full place-items-center rounded-lg border border-border bg-white shadow-sm">
          <Loader2 className="h-6 w-6 animate-spin text-primary" />
        </div>
      </section>
    </main>
  );
}

function CheckoutSteps({ activeStep }: { activeStep: CheckoutStep }) {
  const steps: Array<{ id: CheckoutStep; label: string }> = [
    { id: "address", label: "Address" },
    { id: "payment", label: "Payment" },
    { id: "success", label: "Success" },
  ];
  const activeIndex = steps.findIndex((step) => step.id === activeStep);

  return (
    <div className="grid grid-cols-3 gap-2">
      {steps.map((step, index) => (
        <div
          key={step.id}
          className={`rounded-md border px-3 py-2 text-center text-xs font-black uppercase tracking-[0.12em] ${
            index <= activeIndex
              ? "border-primary bg-primary text-primary-foreground"
              : "border-border bg-white text-muted-foreground"
          }`}
        >
          {step.label}
        </div>
      ))}
    </div>
  );
}

function PaymentModeButton({
  description,
  icon,
  mode,
  onSelect,
  selectedMode,
  title,
}: {
  description: string;
  icon: ReactNode;
  mode: PaymentMode;
  onSelect: (mode: PaymentMode) => void;
  selectedMode: PaymentMode;
  title: string;
}) {
  const isSelected = selectedMode === mode;

  return (
    <button
      type="button"
      onClick={() => onSelect(mode)}
      className={`flex w-full items-center justify-between gap-4 rounded-md border p-4 text-left transition ${
        isSelected
          ? "border-primary bg-primary/5 ring-2 ring-primary/10"
          : "border-border bg-white hover:border-primary/30"
      }`}
    >
      <span className="flex min-w-0 items-start gap-3">
        <span
          className={`grid h-10 w-10 shrink-0 place-items-center rounded-md ${
            isSelected ? "bg-primary text-primary-foreground" : "bg-slate-100 text-muted-foreground"
          }`}
        >
          {icon}
        </span>
        <span className="min-w-0">
          <span className="block font-black text-foreground">{title}</span>
          <span className="mt-1 block text-sm font-bold leading-6 text-muted-foreground">
            {description}
          </span>
        </span>
      </span>
      <span
        className={`grid h-5 w-5 shrink-0 place-items-center rounded-full border ${
          isSelected ? "border-primary bg-primary" : "border-border bg-white"
        }`}
      >
        {isSelected ? <span className="h-2 w-2 rounded-full bg-white" /> : null}
      </span>
    </button>
  );
}

function CheckoutAddressForm({
  isSaving,
  onSave,
}: {
  isSaving: boolean;
  onSave: (event: FormEvent<HTMLFormElement>) => Promise<boolean>;
}) {
  const [draft, setDraft] = useState<AddressDraft>(emptyAddressDraft);
  const [isLocating, setIsLocating] = useState(false);
  const [locationStatus, setLocationStatus] = useState("Fetching your current location...");

  const updateDraft = (key: keyof AddressDraft, value: string) => {
    setDraft((current) => ({ ...current, [key]: value }));
  };

  const applyCoordinates = useCallback(
    async (latitude: number, longitude: number, shouldOverwrite = false) => {
      try {
        const response = await fetch(`${apiBaseUrl}${apiPath("/api/locations/resolve")}`, {
          method: "POST",
          headers: apiHeaders({ "Content-Type": "application/json" }),
          body: JSON.stringify({ lat: latitude, lng: longitude }),
        });
        const data = (await response.json().catch(() => ({}))) as ReverseLocationResponse;

        if (!response.ok) {
          throw new Error("Could not fetch address details");
        }

        const address = data.address ?? {};
        const displayParts = getDisplayNameParts(data.displayName);
        const displaySector = getSectorFromDisplayName(data.displayName);
        const street =
          [address.house_number, address.road ?? address.pedestrian ?? address.footway]
            .filter(Boolean)
            .join(", ") ||
          displayParts[0] ||
          "";
        const sector =
          address.quarter ??
          address.city_block ??
          displaySector ??
          address.neighbourhood ??
          address.suburb ??
          "";
        const locality =
          sector ??
          address.locality ??
          address.residential ??
          address.city_district ??
          address.hamlet ??
          address.village ??
          displayParts[1] ??
          "";
        const city =
          address.city ??
          address.town ??
          address.village ??
          address.county ??
          displayParts.find((part) => /gurugram|gurgaon|delhi|noida|faridabad/i.test(part)) ??
          "";
        const landmark = address.amenity ?? address.building ?? address.shop ?? "";

        setDraft((current) => ({
          ...current,
          houseNo: shouldOverwrite
            ? address.house_number || ""
            : current.houseNo || address.house_number || "",
          street: shouldOverwrite ? street : current.street || street,
          locality: shouldOverwrite ? locality : current.locality || locality,
          city: shouldOverwrite ? city : current.city || city,
          state: shouldOverwrite ? address.state || "" : current.state || address.state || "",
          pincode: shouldOverwrite
            ? address.postcode || ""
            : current.pincode || address.postcode || "",
          landmark: shouldOverwrite ? landmark : current.landmark || landmark,
          latitude,
          longitude,
        }));
        setLocationStatus(data.displayName ?? "Location fetched. Please confirm the details.");
      } catch (error) {
        setDraft((current) => ({ ...current, latitude, longitude }));
        setLocationStatus(
          error instanceof Error
            ? error.message
            : "Location saved, but address details could not be fetched.",
        );
      }
    },
    [],
  );

  const detectLocation = useCallback(async () => {
    if (!navigator.geolocation) {
      setLocationStatus("Location is not supported in this browser.");
      return;
    }

    setIsLocating(true);
    setLocationStatus("Allow location access to auto-fill this address.");

    navigator.geolocation.getCurrentPosition(
      async (position) => {
        const latitude = Number(position.coords.latitude.toFixed(6));
        const longitude = Number(position.coords.longitude.toFixed(6));

        try {
          await applyCoordinates(latitude, longitude);
        } finally {
          setIsLocating(false);
        }
      },
      (error) => {
        setLocationStatus(error.message || "Location permission was not granted.");
        setIsLocating(false);
      },
      { enableHighAccuracy: true, maximumAge: 60_000, timeout: 12_000 },
    );
  }, [applyCoordinates]);

  const selectMapPoint = useCallback(
    async (latitude: number, longitude: number) => {
      setIsLocating(true);
      setLocationStatus("Resolving selected map pin...");

      try {
        await applyCoordinates(latitude, longitude, true);
      } finally {
        setIsLocating(false);
      }
    },
    [applyCoordinates],
  );

  useEffect(() => {
    detectLocation();
  }, [detectLocation]);

  async function handleSubmit(event: FormEvent<HTMLFormElement>) {
    const didSave = await onSave(event);

    if (didSave) {
      setDraft(emptyAddressDraft);
      setLocationStatus("Address saved. Fetch location again for the next address.");
    }
  }

  return (
    <form onSubmit={handleSubmit} className="space-y-3 bg-slate-50 p-4">
      <AddressLocationMap
        latitude={draft.latitude}
        longitude={draft.longitude}
        status={locationStatus}
        isLocating={isLocating}
        onRefresh={detectLocation}
        onPointSelect={selectMapPoint}
      />

      <input type="hidden" name="latitude" value={draft.latitude ?? ""} />
      <input type="hidden" name="longitude" value={draft.longitude ?? ""} />
      <select
        required
        name="type"
        value={draft.type}
        onChange={(event) => updateDraft("type", event.target.value)}
        className={checkoutFieldClass}
      >
        <option value="">Address type</option>
        <option value="home">Home</option>
        <option value="other">Other</option>
      </select>
      <CheckoutInput
        name="houseNo"
        placeholder="House / flat number"
        value={draft.houseNo}
        onChange={(value) => updateDraft("houseNo", value)}
      />
      <CheckoutInput
        name="street"
        placeholder="Street"
        value={draft.street}
        onChange={(value) => updateDraft("street", value)}
      />
      <CheckoutInput
        name="locality"
        placeholder="Locality"
        value={draft.locality}
        onChange={(value) => updateDraft("locality", value)}
      />
      <div className="grid gap-3 sm:grid-cols-3">
        <CheckoutInput
          name="city"
          placeholder="City"
          value={draft.city}
          onChange={(value) => updateDraft("city", value)}
        />
        <CheckoutInput
          name="state"
          placeholder="State"
          value={draft.state}
          onChange={(value) => updateDraft("state", value)}
        />
        <CheckoutInput
          inputMode="numeric"
          maxLength={6}
          name="pincode"
          pattern="[0-9]{6}"
          placeholder="Pincode"
          value={draft.pincode}
          onChange={(value) => updateDraft("pincode", value.replace(/\D/g, "").slice(0, 6))}
        />
      </div>
      <CheckoutInput
        name="landmark"
        placeholder="Landmark"
        required={false}
        value={draft.landmark}
        onChange={(value) => updateDraft("landmark", value)}
      />
      <CheckoutCheckbox name="isDefault" label="Set as default" />
      <CheckoutSaveButton isSaving={isSaving} label="Save address" />
    </form>
  );
}

const checkoutFieldClass =
  "h-11 w-full rounded-md border border-border bg-white px-3 text-sm font-bold outline-none transition focus:border-primary focus:ring-2 focus:ring-primary/15";

function CheckoutInput({
  name,
  maxLength,
  onChange,
  placeholder,
  inputMode,
  pattern,
  required = true,
  value,
}: {
  name: string;
  maxLength?: number;
  onChange?: (value: string) => void;
  placeholder: string;
  inputMode?: "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | "search";
  pattern?: string;
  required?: boolean;
  value?: string;
}) {
  return (
    <input
      name={name}
      maxLength={maxLength}
      placeholder={placeholder}
      inputMode={inputMode}
      pattern={pattern}
      required={required}
      value={value}
      onChange={onChange ? (event) => onChange(event.target.value) : undefined}
      className={checkoutFieldClass}
    />
  );
}

function CheckoutCheckbox({ name, label }: { name: string; label: string }) {
  return (
    <label className="flex items-center gap-2 text-sm font-bold text-muted-foreground">
      <input name={name} type="checkbox" className="h-4 w-4 accent-primary" />
      {label}
    </label>
  );
}

function CheckoutSaveButton({ isSaving, label }: { isSaving: boolean; label: string }) {
  return (
    <button
      disabled={isSaving}
      className="inline-flex h-11 w-full items-center justify-center gap-2 rounded-md bg-primary px-4 text-sm font-black text-primary-foreground disabled:opacity-60"
    >
      {isSaving ? <Loader2 className="h-4 w-4 animate-spin" /> : null}
      {label}
    </button>
  );
}

function SummaryRow({
  label,
  value,
  content,
}: {
  label: string;
  value: string;
  content?: ReactNode;
}) {
  return (
    <div className="flex items-start justify-between gap-4">
      <p className="text-xs font-black uppercase tracking-[0.14em] text-muted-foreground">
        {label}
      </p>
      <div className="text-right text-sm font-black text-foreground">{content ?? value}</div>
    </div>
  );
}

function getPackagePrice(servicePackage: VehiclePackage | null) {
  const price = Number(servicePackage?.finalPrice ?? servicePackage?.basePrice ?? 0);
  return Number.isFinite(price) && price > 0 ? price : 0;
}

function getPackageBasePrice(servicePackage: VehiclePackage | null) {
  const price = Number(
    servicePackage?.displayBasePrice ??
      servicePackage?.basePrice ??
      servicePackage?.finalPrice ??
      0,
  );
  return Number.isFinite(price) && price > 0 ? price : 0;
}

function formatCurrency(value: number) {
  return new Intl.NumberFormat("en-IN", {
    style: "currency",
    currency: "INR",
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  }).format(value);
}

function loadRazorpayCheckoutScript() {
  if (typeof window === "undefined") {
    return Promise.resolve(false);
  }

  if (window.Razorpay) {
    return Promise.resolve(true);
  }

  return new Promise<boolean>((resolve) => {
    const existingScript = document.querySelector<HTMLScriptElement>(
      'script[src="https://checkout.razorpay.com/v1/checkout.js"]',
    );

    if (existingScript) {
      existingScript.addEventListener("load", () => resolve(true), { once: true });
      existingScript.addEventListener("error", () => resolve(false), { once: true });
      return;
    }

    const script = document.createElement("script");
    script.src = "https://checkout.razorpay.com/v1/checkout.js";
    script.async = true;
    script.onload = () => resolve(true);
    script.onerror = () => resolve(false);
    document.body.appendChild(script);
  });
}

function CheckoutPriceBlock({
  servicePackage,
  compact = false,
}: {
  servicePackage: VehiclePackage | null;
  compact?: boolean;
}) {
  const basePrice = getPackageBasePrice(servicePackage);
  const finalPrice = getPackagePrice(servicePackage);

  if (finalPrice <= 0) {
    return <span className="font-black text-foreground">To confirm</span>;
  }

  return (
    <div
      className={compact ? "space-y-0.5" : "rounded-lg border border-primary/20 bg-primary/5 p-4"}
    >
      <div className="flex flex-wrap items-end gap-x-3 gap-y-1">
        {basePrice > 0 ? (
          <span className="text-xs font-black text-muted-foreground line-through decoration-2">
            {formatCurrency(basePrice)}
          </span>
        ) : null}
        <span className={`${compact ? "text-lg" : "text-2xl"} font-black text-primary`}>
          {formatCurrency(finalPrice)}
        </span>
      </div>
      {Number(servicePackage?.discountPercentage ?? 0) > 0 ? (
        <p className="text-xs font-black text-emerald-700">
          {servicePackage?.discountPercentage}% off
        </p>
      ) : null}
    </div>
  );
}

function formatAddressTitle(address: AccountAddress) {
  return formatAddressType(address.type || address.label);
}

function formatAddressType(value: string | null | undefined) {
  if (!value) {
    return "Address";
  }

  return value.charAt(0).toUpperCase() + value.slice(1).toLowerCase();
}

function formatAddressLine(address: AccountAddress) {
  return (
    [
      [address.houseNo, address.street].filter(Boolean).join(", "),
      address.locality,
      address.landmark,
      address.city,
      address.state,
      address.pincode,
    ]
      .filter(Boolean)
      .join(", ") || address.address
  );
}

function getSectorFromDisplayName(displayName: string | null | undefined) {
  const match = displayName?.match(/\bsector\s*[-\w]+/i);

  return match ? match[0].replace(/\s+/g, " ") : undefined;
}

function getDisplayNameParts(displayName: string | null | undefined) {
  return (
    displayName
      ?.split(",")
      .map((part) => part.trim())
      .filter(Boolean) ?? []
  );
}
