"use client";

import { useCallback, useMemo } from "react";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { ShieldCheck } from "lucide-react";

import { PageLayout } from "@/components/templates/PageLayout";
import { SubCard } from "@/components/molecules/SubCard/SubCard";
import { InlineToast } from "@/components/atoms/inline-toast";
import { AddressConfirmation } from "@/features/services/components/base/AddressConfirmation";
import { useCheckoutStore } from "@/features/checkout/stores/checkout.store";
import { ordersService } from "@/features/orders/api/orders.api";
import { usePaymentMethods } from "@/features/billing/hooks/useBilling";
import { usePaymentRefresh } from "@/features/billing/hooks/usePaymentRefresh";
import { billingService } from "@/features/billing/api/billing.api";
import { openSsoLink } from "@/features/billing/utils/sso";
import {
  useResidenceCardVerification,
  useSubmitResidenceCard,
} from "@/features/verification/hooks/useResidenceCardVerification";
import { useAuthSession } from "@/features/auth/stores/auth.store";
import { toOrderTypeValueFromCheckout, type OrderTypeValue } from "@customer-portal/domain/orders";
import { buildPaymentMethodDisplay, formatAddressLabel } from "@/shared/utils";

import { CheckoutStatusBanners } from "./CheckoutStatusBanners";
import {
  PaymentMethodSection,
  IdentityVerificationSection,
  OrderSubmitSection,
} from "./checkout-sections";
import { CheckoutErrorFallback } from "./CheckoutErrorFallback";
import {
  useCheckoutEligibility,
  useCheckoutFormState,
  useCheckoutToast,
  useCanSubmit,
} from "@/features/checkout/hooks";
import {
  buildConfigureBackUrl,
  buildVerificationRedirectUrl,
  buildOrderSuccessUrl,
  getShopHref,
} from "@/features/checkout/utils";

function hasCompleteAddress(address: Record<string, unknown> | null | undefined): boolean {
  if (!address) return false;
  return Boolean(
    address["address1"] &&
    address["city"] &&
    address["postcode"] &&
    (address["country"] || address["countryCode"])
  );
}

function useCheckoutPayment() {
  const { data: paymentMethods, isLoading, error, refetch } = usePaymentMethods();
  const paymentRefresh = usePaymentRefresh({ refetch });
  const { showToast } = useCheckoutToast({ setToast: paymentRefresh.setToast });

  const list = paymentMethods?.paymentMethods ?? [];
  const hasMethod = list.length > 0;
  const defaultMethod = list.find(m => m.isDefault) ?? list[0] ?? null;
  const display = defaultMethod ? buildPaymentMethodDisplay(defaultMethod) : null;

  return { isLoading, error, hasMethod, display, paymentRefresh, showToast };
}

function useCheckoutHandlers(deps: {
  checkoutSessionId: string | null;
  pathname: string;
  searchParams: ReturnType<typeof useSearchParams>;
  router: ReturnType<typeof useRouter>;
  setError: (e: string | null) => void;
  startSubmitting: () => void;
  stopSubmitting: () => void;
  startOpeningPortal: () => void;
  stopOpeningPortal: () => void;
  openingPaymentPortal: boolean;
  showToast: (msg: string, tone: "info" | "success" | "warning" | "error") => void;
}) {
  const formatDateTime = useCallback((iso?: string | null) => {
    if (!iso) return null;
    const date = new Date(iso);
    if (Number.isNaN(date.getTime())) return null;
    return new Intl.DateTimeFormat(undefined, { dateStyle: "medium", timeStyle: "short" }).format(
      date
    );
  }, []);

  const navigateBackToConfigure = useCallback(() => {
    deps.router.push(buildConfigureBackUrl(deps.searchParams));
  }, [deps.router, deps.searchParams]);

  const handleSubmitOrder = useCallback(async () => {
    deps.setError(null);
    if (!deps.checkoutSessionId) {
      deps.setError("Checkout session expired. Please restart checkout from the shop.");
      return;
    }
    try {
      deps.startSubmitting();
      const result = await ordersService.createOrderFromCheckoutSession(deps.checkoutSessionId);
      deps.router.push(buildOrderSuccessUrl(result.sfOrderId));
    } catch (error) {
      const message = error instanceof Error ? error.message : "Order submission failed";
      if (
        message.toLowerCase().includes("residence card submission required") ||
        message.toLowerCase().includes("residence card submission was rejected")
      ) {
        deps.router.push(buildVerificationRedirectUrl(deps.pathname, deps.searchParams));
        return;
      }
      deps.setError(message);
    } finally {
      deps.stopSubmitting();
    }
  }, [deps]);

  const handleManagePayment = useCallback(async () => {
    if (deps.openingPaymentPortal) return;
    deps.startOpeningPortal();
    try {
      const data = await billingService.createPaymentMethodsSsoLink();
      if (!data.url) throw new Error("No payment portal URL returned");
      openSsoLink(data.url, { newTab: true });
    } catch (error) {
      deps.showToast(
        error instanceof Error ? error.message : "Unable to open the payment portal",
        "error"
      );
    } finally {
      deps.stopOpeningPortal();
    }
  }, [deps]);

  return { formatDateTime, navigateBackToConfigure, handleSubmitOrder, handleManagePayment };
}

export function AccountCheckoutContainer() {
  const router = useRouter();
  const pathname = usePathname();
  const searchParams = useSearchParams();
  const { user } = useAuthSession();
  const { cartItem, checkoutSessionId } = useCheckoutStore();

  const orderType: OrderTypeValue | null = useMemo(
    () => toOrderTypeValueFromCheckout(cartItem?.orderType),
    [cartItem?.orderType]
  );

  const {
    formState,
    confirmAddress,
    unconfirmAddress,
    startSubmitting,
    stopSubmitting,
    setError,
    startOpeningPortal,
    stopOpeningPortal,
  } = useCheckoutFormState();
  const { eligibility, eligibilityRequest, activeInternetWarning } = useCheckoutEligibility({
    orderType,
  });
  const payment = useCheckoutPayment();

  const addressLabel = useMemo(() => formatAddressLabel(user?.address), [user?.address]);

  const residenceCardQuery = useResidenceCardVerification();
  const submitResidenceCard = useSubmitResidenceCard();
  const residenceStatus = residenceCardQuery.data?.status;

  const canSubmit = useCanSubmit(formState.addressConfirmed, {
    paymentMethodsLoading: payment.isLoading,
    hasPaymentMethod: payment.hasMethod,
    residenceSubmitted: residenceStatus === "pending" || residenceStatus === "verified",
    eligibility,
  });

  const handlers = useCheckoutHandlers({
    checkoutSessionId,
    pathname,
    searchParams,
    router,
    setError,
    startSubmitting,
    stopSubmitting,
    startOpeningPortal,
    stopOpeningPortal,
    openingPaymentPortal: formState.openingPaymentPortal,
    showToast: payment.showToast,
  });

  if (!cartItem || !orderType) return <CheckoutErrorFallback shopHref={getShopHref(pathname)} />;

  return (
    <PageLayout title="Checkout" icon={<ShieldCheck className="h-6 w-6" />}>
      <div className="max-w-2xl mx-auto space-y-8">
        <InlineToast
          visible={payment.paymentRefresh.toast.visible}
          text={payment.paymentRefresh.toast.text}
          tone={payment.paymentRefresh.toast.tone}
        />

        <CheckoutStatusBanners
          activeInternetWarning={activeInternetWarning}
          eligibility={eligibility}
          eligibilityRequest={{
            isPending: eligibilityRequest.isPending,
            mutate: (data: {
              address?: Partial<NonNullable<typeof user>["address"]> | undefined;
              notes?: string | undefined;
            }) => {
              const { notes, address: addr } = data;
              eligibilityRequest.mutate({
                ...(addr !== undefined && { address: addr }),
                ...(notes !== undefined && { notes }),
              });
            },
          }}
          hasServiceAddress={hasCompleteAddress(user?.address)}
          addressLabel={addressLabel}
          userAddress={user?.address ?? {}}
          planSku={cartItem.planSku}
        />

        <div className="bg-card border border-border rounded-2xl p-6 md:p-7 shadow-[var(--cp-shadow-1)]">
          <div className="flex items-center gap-3 mb-6">
            <ShieldCheck className="w-6 h-6 text-primary" />
            <h2 className="text-lg font-semibold text-foreground">Checkout requirements</h2>
          </div>
          <div className="space-y-5">
            <SubCard>
              <AddressConfirmation
                embedded
                onAddressConfirmed={confirmAddress}
                onAddressIncomplete={unconfirmAddress}
                orderType={orderType}
              />
            </SubCard>
            <PaymentMethodSection
              isLoading={payment.isLoading}
              isError={!!payment.error}
              hasPaymentMethod={payment.hasMethod}
              paymentMethodDisplay={payment.display}
              onManagePayment={() => void handlers.handleManagePayment()}
              onRefresh={() => void payment.paymentRefresh.triggerRefresh()}
              isOpeningPortal={formState.openingPaymentPortal}
            />
            <IdentityVerificationSection
              isLoading={residenceCardQuery.isLoading}
              isError={residenceCardQuery.isError}
              status={residenceStatus}
              data={
                residenceCardQuery.data ?? {
                  submittedAt: null,
                  reviewedAt: null,
                  reviewerNotes: null,
                }
              }
              onRefetch={() => void residenceCardQuery.refetch()}
              onSubmitFile={(file: File) => submitResidenceCard.mutate(file)}
              isSubmitting={submitResidenceCard.isPending}
              submitError={submitResidenceCard.error ?? null}
              formatDateTime={handlers.formatDateTime}
            />
          </div>
        </div>

        <OrderSubmitSection
          pricing={cartItem.pricing}
          submitError={formState.submitError}
          isSubmitting={formState.submitting}
          canSubmit={canSubmit}
          onSubmit={() => void handlers.handleSubmitOrder()}
          onBack={handlers.navigateBackToConfigure}
        />
      </div>
    </PageLayout>
  );
}

export default AccountCheckoutContainer;
