"use client";

import Link from "next/link";
import { useRouter } from "next/navigation";
import { FormEvent, Suspense, useState } from "react";
import {
  DemoCardForm,
  StripeCardForm,
} from "@/components/checkout/StripeCardForm";
import { PageShell } from "@/components/layout/PageShell";
import { SafeImage } from "@/components/ui/SafeImage";
import { useCart } from "@/context/cart-context";
import { useToast } from "@/context/toast-context";
import { createOrderId, saveOrder, type PlacedOrder } from "@/lib/orders";
import { formatPrice } from "@/lib/format";

type ShippingForm = {
  email: string;
  name: string;
  phone: string;
  address: string;
  city: string;
  state: string;
  zip: string;
  country: string;
};

function CheckoutForm() {
  const router = useRouter();
  const { items, subtotal, discount, shipping, total, clearCart, coupon } =
    useCart();
  const { toast } = useToast();
  const [step, setStep] = useState<"details" | "payment">("details");
  const [loading, setLoading] = useState(false);
  const [clientSecret, setClientSecret] = useState<string | null>(null);
  const [mode, setMode] = useState<"stripe" | "demo">("demo");
  const [orderId, setOrderId] = useState("");
  const [chargedTotals, setChargedTotals] = useState<{
    subtotal: number;
    discount: number;
    shipping: number;
    total: number;
  } | null>(null);
  const [form, setForm] = useState<ShippingForm>({
    email: "",
    name: "",
    phone: "",
    address: "",
    city: "",
    state: "",
    zip: "",
    country: "United States",
  });

  if (items.length === 0) {
    return (
      <PageShell
        crumbs={[
          { label: "Home", href: "/" },
          { label: "Cart", href: "/cart" },
          { label: "Checkout" },
        ]}
        title="Checkout"
        description="Your bag is empty."
      >
        <Link
          href="/shop"
          className="inline-flex h-11 items-center rounded-full bg-foreground px-5 text-sm font-semibold text-background"
        >
          Continue shopping
        </Link>
      </PageShell>
    );
  }

  const buildOrder = (
    paymentMethod: "stripe" | "demo",
    paymentId?: string,
  ): PlacedOrder => ({
    id: orderId || createOrderId(),
    createdAt: new Date().toISOString(),
    email: form.email,
    name: form.name,
    phone: form.phone,
    address: form.address,
    city: form.city,
    state: form.state,
    zip: form.zip,
    country: form.country,
    items: items.map((item) => ({
      productId: item.product.id,
      name: item.product.name,
      image: item.product.images[0],
      price: item.product.price,
      quantity: item.quantity,
      variantLabel: item.variantLabel,
    })),
    subtotal: chargedTotals?.subtotal ?? subtotal,
    discount: chargedTotals?.discount ?? discount,
    shipping: chargedTotals?.shipping ?? shipping,
    total: chargedTotals?.total ?? total,
    paymentMethod,
    stripeSessionId: paymentId,
    status: "paid",
  });

  const finishOrder = async (
    paymentMethod: "stripe" | "demo",
    paymentId?: string,
  ) => {
    const order = buildOrder(paymentMethod, paymentId);
    const response = await fetch("/api/orders", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      credentials: "include",
      body: JSON.stringify({
        id: order.id,
        email: order.email,
        name: order.name,
        phone: order.phone,
        address: order.address,
        city: order.city,
        state: order.state,
        zip: order.zip,
        country: order.country,
        items: order.items.map((item) => ({
          productId: item.productId,
          name: item.name,
          price: item.price,
          quantity: item.quantity,
          image: item.image,
          variantLabel: item.variantLabel,
        })),
        subtotal: order.subtotal,
        shipping: order.shipping,
        discount: order.discount,
        total: order.total,
        paymentMethod: order.paymentMethod,
        paymentId: order.stripeSessionId,
      }),
    });
    const data = (await response.json()) as { error?: string };
    if (!response.ok) {
      toast(data.error ?? "Order could not be saved to the database", "error");
      return;
    }
    saveOrder(order);
    clearCart();
    toast("Payment confirmed — order saved");
    router.push(
      `/order/confirmation?order=${encodeURIComponent(order.id)}${
        paymentId ? `&session_id=${encodeURIComponent(paymentId)}` : "&mode=demo"
      }`,
    );
  };

  const onContinueToPayment = async (event: FormEvent) => {
    event.preventDefault();
    setLoading(true);

    try {
      const response = await fetch("/api/checkout", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          ...form,
          items: items.map((item) => ({
            productId: item.product.id,
            quantity: item.quantity,
            variantLabel: item.variantLabel,
          })),
          couponCode: coupon?.code,
        }),
      });
      const data = (await response.json()) as {
        error?: string;
        orderId?: string;
        mode?: string;
        clientSecret?: string | null;
        totals?: {
          subtotal: number;
          discount: number;
          shipping: number;
          total: number;
        };
      };
      if (!response.ok) throw new Error(data.error || "Checkout failed");

      setOrderId(data.orderId || createOrderId());
      setMode(data.mode === "stripe" ? "stripe" : "demo");
      setClientSecret(data.clientSecret ?? null);
      if (data.totals) setChargedTotals(data.totals);
      setStep("payment");
    } catch (error) {
      toast(
        error instanceof Error ? error.message : "Unable to start checkout",
        "error",
      );
    } finally {
      setLoading(false);
    }
  };

  const field = (
    label: string,
    key: keyof ShippingForm,
    opts?: { type?: string },
  ) => (
    <label className="block text-sm">
      <span className="mb-1.5 block font-medium text-foreground">{label}</span>
      <input
        required
        type={opts?.type ?? "text"}
        value={form[key]}
        onChange={(event) =>
          setForm((current) => ({ ...current, [key]: event.target.value }))
        }
        className="h-11 w-full rounded-xl border border-border bg-background px-3 outline-none transition focus:border-foreground"
      />
    </label>
  );

  return (
    <PageShell
      crumbs={[
        { label: "Home", href: "/" },
        { label: "Cart", href: "/cart" },
        { label: "Checkout" },
      ]}
      eyebrow="Secure payment"
      title="Checkout"
      description="Enter shipping details and pay with your card."
    >
      <div className="grid gap-8 lg:grid-cols-[1.1fr_0.9fr]">
        <div className="space-y-6 rounded-[1.35rem] border border-border bg-card p-5 sm:p-6">
          {step === "details" ? (
            <form onSubmit={onContinueToPayment} className="space-y-6">
              <div>
                <h2 className="text-lg font-semibold tracking-tight">
                  Contact & shipping
                </h2>
              </div>
              <div className="grid gap-4 sm:grid-cols-2">
                {field("Email", "email", { type: "email" })}
                {field("Full name", "name")}
                {field("Phone", "phone", { type: "tel" })}
                {field("Country", "country")}
                <div className="sm:col-span-2">{field("Address", "address")}</div>
                {field("City", "city")}
                {field("State", "state")}
                {field("ZIP", "zip")}
              </div>
              <button
                type="submit"
                disabled={loading}
                className="inline-flex h-12 w-full items-center justify-center rounded-full bg-foreground text-sm font-semibold text-background transition hover:opacity-90 disabled:opacity-60"
              >
                {loading ? "Preparing payment…" : "Continue to payment"}
              </button>
            </form>
          ) : (
            <div className="space-y-5">
              <div className="flex items-start justify-between gap-3">
                <div>
                  <h2 className="text-lg font-semibold tracking-tight">
                    Card payment
                  </h2>
                  <p className="mt-1 text-sm text-muted">
                    Pay securely on BhoFit with Stripe.
                  </p>
                </div>
                <button
                  type="button"
                  onClick={() => setStep("details")}
                  className="text-xs font-medium text-muted underline-offset-2 hover:underline"
                >
                  Edit details
                </button>
              </div>

              {mode === "stripe" && clientSecret ? (
                <StripeCardForm
                  clientSecret={clientSecret}
                  billingName={form.name}
                  billingEmail={form.email}
                  onPaid={(paymentIntentId) => {
                    void finishOrder("stripe", paymentIntentId);
                  }}
                  onError={(message) => toast(message, "error")}
                />
              ) : mode === "demo" && process.env.NODE_ENV !== "production" ? (
                <DemoCardForm
                  onPaid={() => {
                    void finishOrder("demo");
                  }}
                />
              ) : (
                <p className="rounded-xl border border-border bg-surface px-4 py-5 text-sm text-muted">
                  Card payments are unavailable right now. Please try again later
                  or contact support.
                </p>
              )}
            </div>
          )}
        </div>

        <aside className="h-fit rounded-[1.35rem] border border-border bg-card p-5 sm:p-6">
          <h2 className="text-lg font-semibold tracking-tight">Order summary</h2>
          <ul className="mt-4 space-y-3">
            {items.map((item) => (
              <li
                key={`${item.product.id}-${item.variantLabel ?? ""}`}
                className="flex gap-3"
              >
                <div className="relative h-16 w-16 shrink-0 overflow-hidden rounded-xl bg-surface">
                  <SafeImage
                    src={item.product.images[0]}
                    alt={item.product.name}
                    fill
                    sizes="64px"
                    className="object-cover"
                  />
                </div>
                <div className="min-w-0 flex-1">
                  <p className="truncate text-sm font-medium">
                    {item.product.name}
                  </p>
                  {item.variantLabel ? (
                    <p className="text-xs text-muted">{item.variantLabel}</p>
                  ) : null}
                  <p className="mt-1 text-xs text-muted">
                    Qty {item.quantity} ·{" "}
                    {formatPrice(item.product.price * item.quantity)}
                  </p>
                </div>
              </li>
            ))}
          </ul>

          <div className="mt-5 space-y-1.5 border-t border-border pt-4 text-sm">
            <div className="flex justify-between text-muted">
              <span>Subtotal</span>
              <span className="tabular-nums">{formatPrice(subtotal)}</span>
            </div>
            <div className="flex justify-between text-muted">
              <span>Discount</span>
              <span className="tabular-nums">−{formatPrice(discount)}</span>
            </div>
            <div className="flex justify-between text-muted">
              <span>Shipping</span>
              <span className="tabular-nums">
                {shipping === 0 ? "Free" : formatPrice(shipping)}
              </span>
            </div>
            <div className="flex justify-between pt-1 text-base font-semibold">
              <span>Total</span>
              <span className="tabular-nums">{formatPrice(total)}</span>
            </div>
          </div>
        </aside>
      </div>
    </PageShell>
  );
}

export default function CheckoutPage() {
  return (
    <Suspense
      fallback={<div className="p-8 text-sm text-muted">Loading checkout…</div>}
    >
      <CheckoutForm />
    </Suspense>
  );
}
