"use client";

import { useState } from "react";
import { CreditCardIcon } from "@heroicons/react/24/outline";
import { PageLayout } from "@/components/templates/PageLayout";
import { ErrorBoundary } from "@/components/molecules";
import { useSession } from "@/features/auth/hooks";
import { useAuthStore } from "@/features/auth/stores/auth.store";
import { isApiError } from "@/core/api";
import { openSsoLink } from "@/features/billing/utils/sso";
import { usePaymentRefresh } from "@/features/billing/hooks/usePaymentRefresh";
import {
  PaymentMethodCard,
  usePaymentMethods,
  useCreatePaymentMethodsSsoLink,
} from "@/features/billing";
import type { PaymentMethodList } from "@customer-portal/domain/payments";
import { InlineToast } from "@/components/atoms/inline-toast";
import { Button } from "@/components/atoms/button";
import { Skeleton } from "@/components/atoms/loading-skeleton";
import { InvoicesList } from "@/features/billing/components/InvoiceList/InvoiceList";
import { logger } from "@/core/logger";

function PaymentMethodsSkeleton() {
  return (
    <div className="bg-card rounded-xl border border-border shadow-[var(--cp-shadow-1)] p-6">
      <div className="flex items-center justify-between mb-6">
        <Skeleton className="h-6 w-48" />
        <Skeleton className="h-10 w-32" />
      </div>
      <div className="space-y-4">
        {Array.from({ length: 2 }).map((_, i) => (
          <div key={i} className="bg-muted rounded-lg p-4">
            <div className="flex items-center justify-between">
              <div className="flex items-center gap-4">
                <Skeleton className="h-12 w-12 rounded-lg" />
                <div className="space-y-2">
                  <Skeleton className="h-5 w-40" />
                  <Skeleton className="h-4 w-24" />
                </div>
              </div>
              <Skeleton className="h-9 w-28" />
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

function PaymentMethodsSection({
  paymentMethodsData,
  onManage,
  isPending,
}: {
  paymentMethodsData: PaymentMethodList;
  onManage: () => void;
  isPending: boolean;
}) {
  const hasMethods = paymentMethodsData.paymentMethods.length > 0;

  return (
    <div className="bg-card rounded-xl border border-border shadow-[var(--cp-shadow-1)] overflow-hidden">
      <div className="px-6 py-5 border-b border-border">
        <div className="flex items-center justify-between">
          <div>
            <h2 className="text-lg font-semibold text-foreground">Payment Methods</h2>
            <p className="text-sm text-muted-foreground mt-0.5">
              {hasMethods
                ? `${paymentMethodsData.paymentMethods.length} payment method${paymentMethodsData.paymentMethods.length === 1 ? "" : "s"} on file`
                : "No payment methods on file"}
            </p>
          </div>
          <Button onClick={onManage} disabled={isPending} size="default">
            {isPending ? "Opening..." : "Manage Cards"}
          </Button>
        </div>
      </div>
      {hasMethods && (
        <div className="p-6">
          <div className="space-y-4">
            {paymentMethodsData.paymentMethods.map(paymentMethod => (
              <PaymentMethodCard key={paymentMethod.id} paymentMethod={paymentMethod} />
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

export function BillingOverview() {
  const [error, setError] = useState<string | null>(null);
  const { isAuthenticated } = useSession();
  const paymentMethodsQuery = usePaymentMethods();
  const {
    data: paymentMethodsData,
    isLoading: isLoadingPaymentMethods,
    isFetching: isFetchingPaymentMethods,
    error: paymentMethodsError,
  } = paymentMethodsQuery;
  const createPaymentMethodsSsoLink = useCreatePaymentMethodsSsoLink();
  const { hasCheckedAuth } = useAuthStore();

  const paymentRefresh = usePaymentRefresh({
    refetch: async () => {
      const result = await paymentMethodsQuery.refetch();
      return { data: result.data };
    },
    hasMethods: data => Boolean(data && (data.totalCount > 0 || data.paymentMethods.length > 0)),
    attachFocusListeners: true,
  });

  const openPaymentMethods = async () => {
    if (!isAuthenticated) {
      setError("Please log in to access payment methods.");
      return;
    }
    setError(null);
    try {
      const ssoLink = await createPaymentMethodsSsoLink.mutateAsync();
      openSsoLink(ssoLink.url, { newTab: true });
    } catch (err: unknown) {
      logger.error("Failed to open payment methods", err);
      if (
        isApiError(err) &&
        "response" in err &&
        typeof err.response === "object" &&
        err.response !== null &&
        "status" in err.response &&
        err.response.status === 401
      ) {
        setError("Authentication failed. Please log in again.");
      } else {
        setError("Unable to access payment methods. Please try again later.");
      }
    }
  };

  const isPaymentLoading = !hasCheckedAuth || isLoadingPaymentMethods || isFetchingPaymentMethods;
  const combinedError = (() => {
    if (error) return new Error(error);
    if (paymentMethodsError instanceof Error) return paymentMethodsError;
    if (paymentMethodsError) return new Error(String(paymentMethodsError));
    return null;
  })();

  return (
    <PageLayout icon={<CreditCardIcon />} title="Billing" error={combinedError}>
      <ErrorBoundary>
        <InlineToast
          visible={paymentRefresh.toast.visible}
          text={paymentRefresh.toast.text}
          tone={paymentRefresh.toast.tone}
        />

        <div className="space-y-8">
          {isPaymentLoading && <PaymentMethodsSkeleton />}
          {!isPaymentLoading && paymentMethodsData && (
            <PaymentMethodsSection
              paymentMethodsData={paymentMethodsData}
              onManage={() => void openPaymentMethods()}
              isPending={createPaymentMethodsSsoLink.isPending}
            />
          )}

          <div>
            <h2 className="text-lg font-semibold text-foreground mb-4">Invoices</h2>
            <InvoicesList />
          </div>
        </div>
      </ErrorBoundary>
    </PageLayout>
  );
}

export default BillingOverview;
