'use client';

import { loadStripe } from '@stripe/stripe-js';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useEffect, useState } from 'react';

import CreditsCompletingStep from '@/app/(root)/account/AuraSubscriptions/modals/steps/credits/CreditsCompletingStep';
import CreditsConfirmStep from '@/app/(root)/account/AuraSubscriptions/modals/steps/credits/CreditsConfirmStep';
import CreditsSelectStep from '@/app/(root)/account/AuraSubscriptions/modals/steps/credits/CreditsSelectStep';
import AuraModal from '@/components/modal/AuraModal';
import { useModalContext } from '@/context/ModalContext';
import useSubscriptionInfo from '@/hooks/useSubscriptionInfo';
import { CheckIcon, ErrorIcon, SparklesIcon } from '@/icons';
import { useApiClient } from '@/lib/apiClient';
import {
  CreditPack,
  CreditPurchase,
  PurchaseStatus,
} from '@/state/sessionStore';
import { ModalStep } from '@/utils/subscriptionModalUtils';

import { ModalTypes } from './constants/ModalTypes';

const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_KEY || '');

const CreditsPurchaseModal = () => {
  const queryClient = useQueryClient();
  const [isLoading, setIsLoading] = useState(false);

  const apiClient = useApiClient();

  const [step, setStep] = useState<ModalStep>(ModalStep.Select);

  const [purchaseId, setPurchaseId] = useState<string | null>(null);
  const [purchaseStatus, setPurchaseStatus] = useState<
    'paid' | 'failed' | 'void' | null
  >(null);

  const query = useSubscriptionInfo();
  const { data: currentSubscription } = query;
  const packs = currentSubscription?.credit_packs || [];

  const [selectedPack, setSelectedPack] = useState<CreditPack | null>(
    currentSubscription?.credit_packs[0] || null
  );

  const { closeModal } = useModalContext();

  // -------- Stripe polling logic --------
  const getPurchaseStatus = async (
    id: string
  ): Promise<PurchaseStatus | null> => {
    const { data } = await apiClient.GET(
      `/api/billing/purchase-credits/{item_id}/`,
      {
        params: { path: { item_id: id } },
      }
    );
    return data ? (data as PurchaseStatus) : null;
  };

  const purchaseStatusQuery = useQuery({
    queryKey: ['purchaseStatus', purchaseId || ''],
    queryFn: () => getPurchaseStatus(purchaseId || ''),
    enabled: !!purchaseId,
    refetchInterval: purchaseId && !purchaseStatus ? 1000 : false,
  });

  useEffect(() => {
    const newStatus = purchaseStatusQuery.data?.status;
    if (newStatus && newStatus !== purchaseStatus) {
      if (
        newStatus === 'paid' ||
        newStatus === 'failed' ||
        newStatus === 'void'
      ) {
        setTimeout(() => {
          setPurchaseStatus(newStatus);
          setIsLoading(false);
          setStep(ModalStep.Completing);
          queryClient.invalidateQueries({ queryKey: ['subscriptionInfo'] });
        }, 2000);
      } else if (newStatus === 'requires_action') {
        const client_secret = purchaseStatusQuery.data?.client_secret;
        if (client_secret) {
          stripePromise.then((stripe) => {
            stripe?.confirmCardPayment(client_secret);
          });
        }
      }
    }
  }, [purchaseStatusQuery.data?.status]);

  // -------- Purchase mutation --------
  const purchaseMutation = useMutation({
    mutationFn: async ({ id, amount }: { id: string; amount: number }) => {
      const { data } = await apiClient.POST('/api/billing/purchase-credits/', {
        body: { id, amount },
      });
      return data as CreditPurchase;
    },
    onSuccess: (data) => {
      setPurchaseId(data.id);
    },
    onError: () => {
      setPurchaseStatus('failed');
      setIsLoading(false);
      setStep(ModalStep.Completing);
    },
  });

  const onClose = () => {
    setStep(ModalStep.Select);
    setPurchaseId(null);
    setPurchaseStatus(null);
    setSelectedPack(packs[0] || null);
    closeModal(ModalTypes.CREDITS_PURCHASE);
  };

  // -------- Modal visuals --------
  const modalIcon = () => {
    if (step === ModalStep.Completing) {
      return purchaseStatus === 'paid' ? (
        <CheckIcon className='h-[24px] w-[24px]' />
      ) : (
        <ErrorIcon className='h-[24px] w-[24px]' />
      );
    }
    return <SparklesIcon className='h-[24px] w-[24px]' />;
  };

  const modalTitle = () => {
    switch (step) {
      case ModalStep.Select:
        return 'Buy Credits';
      case ModalStep.Confirm:
        return 'Confirm your purchase';
      case ModalStep.Completing:
        return purchaseStatus === 'paid' ? 'Success' : 'An Error Occurred';
    }
  };

  // -------- Render step content --------
  const renderStep = () => {
    if (step === ModalStep.Select) {
      return (
        <CreditsSelectStep
          packs={packs}
          selectedPack={selectedPack}
          onSelect={setSelectedPack}
          onContinue={() => setStep(ModalStep.Confirm)}
        />
      );
    }

    if (step === ModalStep.Confirm && selectedPack) {
      return (
        <CreditsConfirmStep
          selectedPack={selectedPack}
          isLoading={isLoading}
          onBack={() => setStep(ModalStep.Select)}
          onConfirm={() => {
            if (selectedPack.id && selectedPack.amount) {
              purchaseMutation.mutate({
                id: selectedPack.id,
                amount: selectedPack.amount,
              });
            } else {
              console.error('Selected pack is invalid');
            }
            setIsLoading(true);
          }}
        />
      );
    }

    return (
      <CreditsCompletingStep
        purchaseStatus={purchaseStatus}
        onClose={onClose}
      />
    );
  };

  return (
    <AuraModal
      open={true}
      onOpenChange={(open) => {
        if (!open) onClose();
      }}
      title={modalTitle()}
      icon={modalIcon()}
    >
      {renderStep()}
    </AuraModal>
  );
};

export default CreditsPurchaseModal;
