"use client";

import { Alert, Button, Card, Separator, Spinner } from "@heroui/react";
import { useEffect, useRef } from "react";

import { useShippingRate } from "@/lib/checkout";
import type {
  CheckoutAddress,
  CheckoutValidationResult,
  CheckoutSelectedShippingRate,
  CheckoutShippingRateResult,
} from "@/lib/checkout/types";
import { formatPrice } from "@repo/utils";
import { CheckoutLineItems } from "../content/CheckoutLineItems";

type OrderReviewStepProps = {
  addressId: string;
  addresses: CheckoutAddress[];
  cartResult: CheckoutValidationResult;
  sessionId: string | undefined;
  onProceed: (
    shipmentObjectId: string,
    shippingRate: CheckoutSelectedShippingRate,
  ) => void;
  onBack: () => void;
};

function formatShippingAmount(amount: number, currency: string): string {
  return new Intl.NumberFormat("en-GB", {
    style: "currency",
    currency: currency || "GBP",
    minimumFractionDigits: 2,
  }).format(amount);
}

export function OrderReviewStep({
  addressId,
  addresses,
  cartResult,
  sessionId,
  onProceed,
  onBack,
}: OrderReviewStepProps) {
  const { result, isLoading, error, retry } = useShippingRate(
    addressId,
    sessionId,
  );

  const prevSubtotalRef = useRef(cartResult.subtotal);

  useEffect(() => {
    if (
      result &&
      !isLoading &&
      cartResult.subtotal !== result.cartSubtotal
    ) {
      prevSubtotalRef.current = cartResult.subtotal;
      retry();
    }
  }, [cartResult.subtotal, result, isLoading, retry]);

  const selectedAddress = addresses.find((a) => a.id === addressId);
  const itemCount = cartResult.items.reduce((sum, i) => sum + i.quantity, 0);

  const canProceed = !!result && !isLoading && !error;

  const handleContinue = () => {
    if (!result) return;
    onProceed(result.shipmentObjectId, result.selectedRate);
  };

  const loadingMessageId = "shipping-rate-loading";
  const errorMessageId = "shipping-rate-error";

  return (
    <div className="flex flex-col gap-6">
      <div className="grid grid-cols-1 gap-6 lg:grid-cols-[1fr,340px] lg:items-start">
        {/* Left column: shipping rate + address + line items */}
        <div className="flex flex-col gap-6">
          <ShippingRateCard
            result={result}
            isLoading={isLoading}
            error={error}
            onRetry={retry}
            loadingMessageId={loadingMessageId}
            errorMessageId={errorMessageId}
          />

          {selectedAddress && (
            <section aria-label="Shipping address">
              <h3 className="mb-2 text-sm font-semibold text-foreground">
                Shipping address
              </h3>
              <AddressPreview address={selectedAddress} />
            </section>
          )}

          <section aria-label="Order items">
            <h3 className="mb-3 text-sm font-semibold text-foreground">
              Items ({itemCount})
            </h3>
            <CheckoutLineItems
              items={cartResult.items}
              issues={cartResult.issues}
            />
          </section>
        </div>

        {/* Right column: sticky order summary */}
        <div className="lg:sticky lg:top-8 lg:self-start">
          <Card className="rounded-lg p-4">
            <Card.Content className="flex flex-col gap-4 p-0">
              <OrderSummary
                cartSubtotal={cartResult.subtotal}
                itemCount={itemCount}
                result={result}
                isLoading={isLoading}
              />

              <div className="flex flex-col gap-2">
                <Button
                  variant="primary"
                  className="w-full bg-[#236f6b] font-medium text-white"
                  size="lg"
                  onPress={handleContinue}
                  isDisabled={!canProceed}
                  aria-disabled={!canProceed || undefined}
                  aria-describedby={
                    isLoading
                      ? loadingMessageId
                      : error
                        ? errorMessageId
                        : undefined
                  }
                >
                  Continue to payment
                </Button>
                <Button
                  variant="ghost"
                  className="w-full md:w-auto"
                  onPress={onBack}
                >
                  Back to address
                </Button>
              </div>
            </Card.Content>
          </Card>
        </div>
      </div>
    </div>
  );
}

// ─── Shipping Rate Card ──────────────────────────────────────────────────────

function ShippingRateCard({
  result,
  isLoading,
  error,
  onRetry,
  loadingMessageId,
  errorMessageId,
}: {
  result: CheckoutShippingRateResult | null;
  isLoading: boolean;
  error: string | null;
  onRetry: () => void;
  loadingMessageId: string;
  errorMessageId: string;
}) {
  if (isLoading) {
    return (
      <Card className="rounded-lg p-4">
        <Card.Content
          className="flex items-center gap-3 p-0"
          role="status"
          id={loadingMessageId}
        >
          <Spinner size="sm" />
          <p className="text-sm text-default-500">
            Calculating best shipping rate…
          </p>
        </Card.Content>
      </Card>
    );
  }

  if (error) {
    return (
      <div id={errorMessageId}>
        <Alert status="danger" role="alert">
          <Alert.Indicator />
          <Alert.Content>
            <Alert.Title>Unable to calculate shipping</Alert.Title>
            <Alert.Description>{error}</Alert.Description>
          </Alert.Content>
        </Alert>
        <Button
          variant="ghost"
          className="mt-3 w-full md:w-auto"
          onPress={onRetry}
        >
          Retry
        </Button>
      </div>
    );
  }

  if (!result) return null;

  const { selectedRate } = result;

  return (
    <Card className="rounded-lg p-4">
      <Card.Content className="flex flex-col gap-1 p-0">
        <div className="flex items-center justify-between">
          <div className="flex items-center gap-2">
            <TruckIcon />
            <span className="text-sm font-semibold text-foreground">
              {selectedRate.provider}
            </span>
          </div>
          <span className="text-sm font-semibold text-[#236f6b]">
            {formatShippingAmount(selectedRate.amount, selectedRate.currency)}
          </span>
        </div>
        <p className="text-sm text-default-500">
          {selectedRate.serviceName}
          {selectedRate.durationTerms && (
            <span> · {selectedRate.durationTerms}</span>
          )}
        </p>
        {selectedRate.estimatedDays > 0 && (
          <p className="text-xs text-default-400">
            Est. {selectedRate.estimatedDays} business{" "}
            {selectedRate.estimatedDays === 1 ? "day" : "days"}
          </p>
        )}
      </Card.Content>
    </Card>
  );
}

// ─── Order Summary ───────────────────────────────────────────────────────────

function OrderSummary({
  cartSubtotal,
  itemCount,
  result,
  isLoading,
}: {
  cartSubtotal: number;
  itemCount: number;
  result: CheckoutShippingRateResult | null;
  isLoading: boolean;
}) {
  const currency = result?.selectedRate.currency ?? "GBP";
  const shippingAmount = result?.shippingTotal ?? null;
  const orderTotal =
    shippingAmount !== null ? cartSubtotal / 100 + shippingAmount : null;

  return (
    <section aria-label="Order summary">
      <h2 className="mb-3 font-[family-name:var(--font-fraunces)] text-lg font-semibold">
        Summary
      </h2>
      <dl className="flex flex-col gap-3">
        <div className="flex items-center justify-between text-sm">
          <dt className="text-default-500">Items ({itemCount})</dt>
          <dd className="font-semibold text-foreground">
            {formatPrice(cartSubtotal)}
          </dd>
        </div>
        <div className="flex items-center justify-between text-sm">
          <dt className="text-default-500">Shipping</dt>
          <dd
            className={
              shippingAmount !== null
                ? "font-semibold text-foreground"
                : "text-default-400"
            }
          >
            {isLoading
              ? "Calculating…"
              : shippingAmount !== null
                ? formatShippingAmount(shippingAmount, currency)
                : "—"}
          </dd>
        </div>
        <Separator />
        <div className="flex items-center justify-between">
          <dt className="font-medium text-foreground">Total</dt>
          <dd className="text-lg font-bold text-[#236f6b]">
            {orderTotal !== null
              ? formatShippingAmount(orderTotal, currency)
              : "—"}
          </dd>
        </div>
      </dl>
    </section>
  );
}

// ─── Address Preview ─────────────────────────────────────────────────────────

function AddressPreview({ address }: { address: CheckoutAddress }) {
  return (
    <div className="rounded-md border border-default-200 p-3 text-sm text-default-600">
      <p className="font-medium text-foreground">{address.fullName}</p>
      <p>{address.addressLine1}</p>
      {address.additionalInformation && <p>{address.additionalInformation}</p>}
      <p>{address.city}</p>
      <p>{address.postalCode}</p>
    </div>
  );
}

// ─── Icons ───────────────────────────────────────────────────────────────────

function TruckIcon() {
  return (
    <svg
      width="18"
      height="18"
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth="2"
      strokeLinecap="round"
      strokeLinejoin="round"
      className="text-[#236f6b]"
      aria-hidden="true"
    >
      <path d="M14 18V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v11a1 1 0 0 0 1 1h2" />
      <path d="M15 18H9" />
      <path d="M19 18h2a1 1 0 0 0 1-1v-3.65a1 1 0 0 0-.22-.624l-3.48-4.35A1 1 0 0 0 17.52 8H14" />
      <circle cx="17" cy="18" r="2" />
      <circle cx="7" cy="18" r="2" />
    </svg>
  );
}
