'use client';

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

import { useStores } from '@/app/(root)/AppProviders';
import { ButtonVariant } from '@/components/button/Button';
import { ModalTypes } from '@/components/modal/constants/ModalTypes';
import SpinnerSVG from '@/components/svg/SpinnerSVG';
import { toast } from '@/components/toast/Toast';
import { useModalContext } from '@/context/ModalContext';
import { useApiClient } from '@/lib/apiClient';
import logWebUserEvent from '@/logging/logWebUserEvent';
import {
  DiscountOfferWithRedemption,
  SubscriptionInfo,
} from '@/state/sessionStore';
import { ModalStep } from '@/utils/subscriptionModalUtils';

import { SUBSCRIPTION_PAGE_VERSIONS } from '../../constants';
import { ModalButton } from './shared/ModalButton';
import { useCancelSubscription } from './shared/hooks';
import CancelConfirmStep from './steps/cancel/CancelConfirmStep';
import CancelScheduledStep from './steps/cancel/CancelScheduledStep';
import CancelSurveyStep from './steps/cancel/CancelSurveyStep';
import ConfirmUpdateStep from './steps/cancel/ConfirmUpdateStep';
import PanicOfferStep from './steps/cancel/PanicOfferStep';
import SurveyOtherStep from './steps/cancel/SurveyOtherStep';

interface CancelSubscriptionModalContentProps {
  currentSubscription: SubscriptionInfo;
  onClose: () => void;
  step?: ModalStep;
  onStepChange?: (step: ModalStep) => void;
  isOpen?: boolean;
}

const CancelSubscriptionModalContent: React.FC<
  CancelSubscriptionModalContentProps
> = ({
  currentSubscription,
  onClose,
  step: externalStep,
  onStepChange,
  isOpen,
}) => {
  const apiClient = useApiClient();
  const queryClient = useQueryClient();
  const { session } = useStores();
  const { openModal, closeModal } = useModalContext();

  const [isCancelLoading, setIsCancelLoading] = useState(false);
  const [isDiscountLoading, setIsDiscountLoading] = useState(false);
  const [internalStep, setInternalStep] = useState<ModalStep>(
    ModalStep.Confirm
  );
  const [discountOffer, setDiscountOffer] =
    useState<DiscountOfferWithRedemption | null>(null);
  const [isConfirmLoading, setIsConfirmLoading] = useState(false);
  const [hasAcceptedOffer, setHasAcceptedOffer] = useState(false);
  const [userMessage, setUserMessage] = useState<string | null>(null);
  const [isSurveyLoading, setIsSurveyLoading] = useState(false);

  const step = externalStep ?? internalStep;
  const setStep = (newStep: ModalStep) => {
    if (onStepChange) {
      onStepChange(newStep);
    } else {
      setInternalStep(newStep);
    }
  };

  // Manual sync with global modal context for playbar hiding functionality
  // TODO: Refactor subscription modals to use global modal infrastructure (openModal/closeModal context)
  // This component exists outside the standard modal system and needs manual sync for UI state like playbar hiding
  // Consider moving to ModalContext pattern to decouple logic and handle content screens automatically
  useEffect(() => {
    if (isOpen) {
      openModal(ModalTypes.CANCEL_SUBSCRIPTION);
    } else {
      closeModal(ModalTypes.CANCEL_SUBSCRIPTION);
    }
  }, [isOpen, openModal, closeModal]); // openModal/closeModal should be stable references

  // Clear state when modal closes completely
  useEffect(() => {
    if (!isOpen) {
      setHasAcceptedOffer(false);
      setDiscountOffer(null);
      setUserMessage(null);
      setIsCancelLoading(false);
      setIsDiscountLoading(false);
      setIsConfirmLoading(false);
      setIsSurveyLoading(false);
    }
  }, [isOpen]);

  // Fetch discount offer data when modal opens
  useEffect(() => {
    if (isOpen) {
      const fetchDiscountOffer = async () => {
        try {
          const { data } = await apiClient.GET(
            '/api/billing/get-discount-offer'
          );
          const fetchedDiscountOffer = data?.discount_offer || null;
          setDiscountOffer(fetchedDiscountOffer);

          // Check if user has already accepted an offer
          const userHasAcceptedOffer =
            fetchedDiscountOffer?.is_accepted ||
            (fetchedDiscountOffer?.accepted_at &&
              !fetchedDiscountOffer?.redeemed_at);
          setHasAcceptedOffer(!!userHasAcceptedOffer);

          if (userHasAcceptedOffer && fetchedDiscountOffer) {
            // Prepare the coupon message for users with accepted offers
            const durationText =
              fetchedDiscountOffer.duration_months === 1
                ? 'next month'
                : `next ${fetchedDiscountOffer.duration_months} months`;

            let couponMessage;
            if (fetchedDiscountOffer.percent_off) {
              couponMessage = `You will miss out on your offer for ${fetchedDiscountOffer.percent_off}% off your ${durationText}.`;
            } else if (fetchedDiscountOffer.amount_off) {
              couponMessage = `You will miss out on your $${fetchedDiscountOffer.amount_off} offer for ${durationText}.`;
            } else {
              couponMessage = `You will miss out on your offer for ${durationText}.`;
            }
            setUserMessage(couponMessage);
          }
        } catch (error) {
          console.error('Error fetching discount offer:', error);
        }
      };

      fetchDiscountOffer();
    }
  }, [isOpen, apiClient]);

  const cancelMutation = useCancelSubscription(apiClient, {
    onMutate: () => setIsCancelLoading(true),
    onSuccess: () => {
      setTimeout(() => {
        setIsCancelLoading(false);
        setIsSurveyLoading(false); // Clear survey loading state too
        setStep(ModalStep.Scheduled);
        toast({
          title: 'Subscription cancelled.',
          status: 'info',
          duration: 3000,
          isClosable: true,
        });
        // Invalidate cache after showing success state to ensure fresh data on next load
        queryClient.invalidateQueries({ queryKey: ['subscriptionInfo'] });
        queryClient.invalidateQueries({ queryKey: ['subscription'] });
      }, 4000);
    },
    onError: () => {
      setIsCancelLoading(false);
      setIsSurveyLoading(false); // Clear survey loading state on error too
    },
  });

  const surveyMutation = useMutation({
    mutationFn: async ({
      reason,
      customReason,
    }: {
      reason: string;
      customReason: string | null;
    }) => {
      return await apiClient.POST('/api/billing/submit-survey/', {
        body: {
          reason: reason as any,
          custom_reason: customReason,
        },
      });
    },
    onMutate: () => setIsSurveyLoading(true),
    onSuccess: () => {
      // After survey is submitted, proceed with cancellation
      // Keep survey loading state active until cancellation completes
      handleConfirmCancel();
    },
    onError: (error) => {
      console.error('Error submitting survey:', error);
      // Still proceed with cancellation even if survey fails
      handleConfirmCancel();
    },
    // Don't clear loading state here - let cancel mutation handle it
  });

  const handleConfirmCancel = () => {
    // The backend cancel endpoint should handle clearing discount redemptions
    // when a user has accepted an offer but confirms cancellation
    if (!session.flags?.['enable-web-sub-retention-offer']) {
      logWebUserEvent({
        actionName: 'ConfirmCancelPlanButtonClicked',
        context: {
          currentPeriod: currentSubscription?.period || '',
          currentUsagePlanId: currentSubscription?.plan?.id || '',
          subPageVersion: SUBSCRIPTION_PAGE_VERSIONS.aura,
          hasAcceptedOffer: hasAcceptedOffer,
        },
      });
    }
    cancelMutation.mutate(undefined);
  };

  const handleDisplayPanicOffer = async () => {
    setIsDiscountLoading(true);

    try {
      let currentDiscountOffer = discountOffer;
      let currentHasAcceptedOffer = hasAcceptedOffer;

      // If we don't have discount offer data, fetch it
      if (!currentDiscountOffer) {
        const { data } = await apiClient.GET('/api/billing/get-discount-offer');
        currentDiscountOffer = data?.discount_offer || null;
        setDiscountOffer(currentDiscountOffer);

        // Recalculate hasAcceptedOffer with fresh data
        const userHasAcceptedOffer =
          currentDiscountOffer?.is_accepted ||
          (currentDiscountOffer?.accepted_at &&
            !currentDiscountOffer?.redeemed_at);
        currentHasAcceptedOffer = !!userHasAcceptedOffer;
        setHasAcceptedOffer(currentHasAcceptedOffer);
      }

      if (currentDiscountOffer && currentSubscription.plan) {
        if (currentHasAcceptedOffer) {
          // Show different confirmation for users who already accepted an offer
          const durationText =
            currentDiscountOffer.duration_months === 1
              ? 'next month'
              : `next ${currentDiscountOffer.duration_months} months`;

          let couponMessage;
          if (currentDiscountOffer.percent_off) {
            couponMessage = `Are you sure? You will miss out on your coupon for ${currentDiscountOffer.percent_off}% off your ${durationText}.`;
          } else if (currentDiscountOffer.amount_off) {
            couponMessage = `Are you sure? You will miss out on your $${currentDiscountOffer.amount_off} coupon for ${durationText}.`;
          } else {
            couponMessage = `Are you sure? You will miss out on your coupon for ${durationText}.`;
          }
          setUserMessage(couponMessage);
          setStep(ModalStep.Confirm);
          logWebUserEvent({
            actionName: 'SubCancelFlowFeaturesAboutToLoseStepShown',
            context: {
              currentPeriod: currentSubscription?.period || '',
              currentUsagePlanId: currentSubscription?.plan?.id || '',
              modalStep: 1,
            },
          });
          return;
        } else {
          // Show the panic offer for first-time cancellers
          setStep(ModalStep.Offer);
          logWebUserEvent({
            actionName: 'SubCancelFlowPanicOfferStepShown',
            context: {
              currentPeriod: currentSubscription?.period || '',
              currentUsagePlanId: currentSubscription?.plan?.id || '',
              stripeCouponId: currentDiscountOffer.stripe_coupon_id || '',
              modalStep: 2,
            },
          });
          return;
        }
      }
    } catch (error) {
      console.error('Error fetching discount offer:', error);
    } finally {
      setIsDiscountLoading(false);
    }

    setStep(ModalStep.CancelSurvey);
    logWebUserEvent({
      actionName: 'SubCancelFlowSurveyStepShown',
      context: {
        currentPeriod: currentSubscription?.period || '',
        currentUsagePlanId: currentSubscription?.plan?.id || '',
        stripeCouponId: discountOffer?.stripe_coupon_id || '',
        modalStep: 3,
      },
    });
  };

  const handleAcceptOffer = () => {
    setStep(ModalStep.ConfirmOffer);
    logWebUserEvent({
      actionName: 'SubCancelFlowConfirmUpdatedInvoiceDetailsStepShown',
      context: {
        currentPeriod: currentSubscription?.period || '',
        currentUsagePlanId: currentSubscription?.plan?.id || '',
        stripeCouponId: discountOffer?.stripe_coupon_id || '',
        modalStep: 3,
      },
    });
  };

  const handleKeep = () => {
    logWebUserEvent({
      actionName: 'KeepMySubscriptionButtonClicked',
      context: {
        currentPeriod: currentSubscription?.period || '',
        currentUsagePlanId: currentSubscription?.plan?.id || '',
        subPageVersion: SUBSCRIPTION_PAGE_VERSIONS.aura,
      },
    });
    onClose();
  };

  const handleBack = () => {
    if (step === ModalStep.Offer) {
      setStep(ModalStep.Confirm);
      logWebUserEvent({
        actionName: 'SubCancelFlowFeaturesAboutToLoseStepShown',
        context: {
          currentPeriod: currentSubscription?.period || '',
          currentUsagePlanId: currentSubscription?.plan?.id || '',
          modalStep: 1,
        },
      });
    } else if (step === ModalStep.ConfirmOffer) {
      setStep(ModalStep.Offer);
      logWebUserEvent({
        actionName: 'SubCancelFlowPanicOfferStepShown',
        context: {
          currentPeriod: currentSubscription?.period || '',
          currentUsagePlanId: currentSubscription?.plan?.id || '',
          stripeCouponId: discountOffer?.stripe_coupon_id || '',
          modalStep: 2,
        },
      });
    } else if (step === ModalStep.CouponConfirm) {
      setStep(ModalStep.Confirm);
      logWebUserEvent({
        actionName: 'SubCancelFlowFeaturesAboutToLoseStepShown',
        context: {
          currentPeriod: currentSubscription?.period || '',
          currentUsagePlanId: currentSubscription?.plan?.id || '',
          modalStep: 1,
        },
      });
    } else if (step === ModalStep.SurveyOther) {
      setStep(ModalStep.CancelSurvey);
      logWebUserEvent({
        actionName: 'SubCancelFlowSurveyStepShown',
        context: {
          currentPeriod: currentSubscription?.period || '',
          currentUsagePlanId: currentSubscription?.plan?.id || '',
          stripeCouponId: discountOffer?.stripe_coupon_id || '',
          modalStep: 3,
        },
      });
    } else if (step === ModalStep.CancelSurvey) {
      // Go back to coupon confirm if user has accepted offer, otherwise to panic offer or confirm
      if (hasAcceptedOffer) {
        setStep(ModalStep.CouponConfirm);
        logWebUserEvent({
          actionName: 'SubCancelFlowAboutToLoseAcceptedOfferStepShown',
          context: {
            currentPeriod: currentSubscription?.period || '',
            currentUsagePlanId: currentSubscription?.plan?.id || '',
            stripeCouponId: discountOffer?.stripe_coupon_id || '',
            modalStep: 2,
          },
        });
      } else if (discountOffer && currentSubscription.plan) {
        setStep(ModalStep.Offer);
        logWebUserEvent({
          actionName: 'SubCancelFlowPanicOfferStepShown',
          context: {
            currentPeriod: currentSubscription?.period || '',
            currentUsagePlanId: currentSubscription?.plan?.id || '',
            stripeCouponId: discountOffer?.stripe_coupon_id || '',
            modalStep: 2,
          },
        });
      } else {
        setStep(ModalStep.Confirm);
        logWebUserEvent({
          actionName: 'SubCancelFlowFeaturesAboutToLoseStepShown',
          context: {
            currentPeriod: currentSubscription?.period || '',
            currentUsagePlanId: currentSubscription?.plan?.id || '',
            modalStep: 1,
          },
        });
      }
    } else {
      onClose();
    }
  };

  const handleConfirmOffer = async () => {
    if (!discountOffer?.stripe_coupon_id) {
      console.error('No coupon ID available');
      return;
    }

    setIsConfirmLoading(true);
    try {
      const { data } = await apiClient.POST('/api/billing/accept-sub-coupon/', {
        body: {
          coupon_id: discountOffer.stripe_coupon_id,
        },
      });
      if (data?.success) {
        toast({
          title: 'Discount applied',
          status: 'info',
          duration: 3000,
          isClosable: true,
        });
        onClose();
      }
    } catch (error) {
      console.error('Error accepting discount offer:', error);
    } finally {
      setIsConfirmLoading(false);
    }
  };

  const handleSurveyReasonSelected = (reason: string) => {
    if (reason === 'other') {
      setStep(ModalStep.SurveyOther);
      logWebUserEvent({
        actionName: 'SubCancelFlowSurveyOtherStepShown',
        context: {
          currentPeriod: currentSubscription?.period || '',
          currentUsagePlanId: currentSubscription?.plan?.id || '',
          stripeCouponId: discountOffer?.stripe_coupon_id || '',
          modalStep: 4,
        },
      });
    } else {
      // Submit survey with selected reason and proceed to cancel
      surveyMutation.mutate({ reason, customReason: null });
      logWebUserEvent({
        actionName: 'SubCancelFlowChurnReasonSurveySubmitted',
        context: {
          reason: reason,
          customReason: '',
        },
      });
    }
  };

  const handleSurveyOtherSubmit = (customReason: string) => {
    surveyMutation.mutate({ reason: 'other', customReason });
    logWebUserEvent({
      actionName: 'SubCancelFlowChurnReasonSurveySubmitted',
      context: {
        reason: 'other',
        customReason: customReason,
      },
    });
  };

  if (step === ModalStep.Confirm) {
    return (
      <CancelConfirmStep
        currentSubscription={currentSubscription}
        isCancelLoading={isCancelLoading || isDiscountLoading}
        onKeep={handleKeep}
        onConfirmCancel={
          hasAcceptedOffer
            ? () => {
                setStep(ModalStep.CouponConfirm);
                logWebUserEvent({
                  actionName: 'SubCancelFlowAboutToLoseAcceptedOfferStepShown',
                  context: {
                    currentPeriod: currentSubscription?.period || '',
                    currentUsagePlanId: currentSubscription?.plan?.id || '',
                    stripeCouponId: discountOffer?.stripe_coupon_id || '',
                    modalStep: 2,
                  },
                });
              }
            : handleDisplayPanicOffer
        }
      />
    );
  } else if (step === ModalStep.CouponConfirm) {
    // Show loading state while data is being fetched
    if (!userMessage || !discountOffer) {
      return (
        <div className='flex items-center justify-center py-8'>
          <SpinnerSVG className='fill-white' />
        </div>
      );
    }

    const planName = currentSubscription?.plan?.name?.split(' ')[0] ?? '';
    const currentPrice = currentSubscription?.plan?.monthly_price_usd ?? 0;

    // Handle both amount_off and percent_off being undefined
    let discountedPrice = currentPrice;
    let discountAmount = '0%';

    if (discountOffer.amount_off && discountOffer.amount_off > 0) {
      discountedPrice = currentPrice - discountOffer.amount_off;
      discountAmount = `$${discountOffer.amount_off}`;
    } else if (discountOffer.percent_off && discountOffer.percent_off > 0) {
      discountedPrice = currentPrice * (1 - discountOffer.percent_off / 100);
      discountAmount = `${discountOffer.percent_off}%`;
    }

    return (
      <div>
        <p className='-mt-4 mb-4 text-white/80'>{userMessage}</p>

        <div className='mb-12 rounded-3xl bg-white/10 p-4'>
          <div className='mx-auto mb-4 max-w-xs text-center leading-relaxed'>
            Keep Suno {planName} and all its benefits at a {discountAmount}{' '}
            discount for your next{' '}
            {discountOffer.duration_months === 1
              ? 'month'
              : `${discountOffer.duration_months} months`}
            !
          </div>

          <div className='mb-4 flex items-center justify-center gap-6'>
            <div className='flex items-baseline gap-1 text-foreground-tertiary'>
              <span className='text-2xl leading-none font-medium line-through'>
                ${currentPrice}
              </span>
              <span className='text-sm leading-none'>total</span>
            </div>
            <div className='flex items-baseline gap-1 text-accent-pink-on-primary'>
              <span className='text-2xl leading-none font-medium'>
                ${discountedPrice}
              </span>
              <span className='text-sm leading-none'>total</span>
            </div>
          </div>

          <ModalButton
            variant={ButtonVariant.Primary}
            className='w-full'
            onClick={() => {
              logWebUserEvent({
                actionName: 'KeepMySubscriptionButtonClicked',
                context: {
                  currentPeriod: currentSubscription?.period || '',
                  currentUsagePlanId: currentSubscription?.plan?.id || '',
                  subPageVersion: SUBSCRIPTION_PAGE_VERSIONS.aura,
                },
              });
              toast({
                title: 'Subscription retained',
                status: 'info',
                duration: 3000,
                isClosable: true,
              });
              onClose();
            }}
          >
            Keep offer
          </ModalButton>
        </div>

        <div className='-mt-4 flex justify-center gap-3'>
          <ModalButton variant={ButtonVariant.Secondary} onClick={handleBack}>
            Back
          </ModalButton>
          <ModalButton
            variant={ButtonVariant.Secondary}
            onClick={() => {
              setStep(ModalStep.CancelSurvey);
              logWebUserEvent({
                actionName: 'SubCancelFlowSurveyStepShown',
                context: {
                  currentPeriod: currentSubscription?.period || '',
                  currentUsagePlanId: currentSubscription?.plan?.id || '',
                  stripeCouponId: discountOffer?.stripe_coupon_id || '',
                  modalStep: 3,
                },
              });
            }}
            disabled={isCancelLoading}
            icon={
              isCancelLoading ? <SpinnerSVG className='fill-black' /> : null
            }
          >
            {isCancelLoading ? 'Confirming...' : 'Confirm Cancellation'}
          </ModalButton>
        </div>
      </div>
    );
  } else if (
    step === ModalStep.Offer &&
    discountOffer &&
    currentSubscription.plan
  ) {
    return (
      <PanicOfferStep
        currentSubscription={currentSubscription}
        isCancelLoading={isCancelLoading}
        discountOffer={discountOffer}
        onBack={handleBack}
        onConfirmCancel={() => {
          setStep(ModalStep.CancelSurvey);
          logWebUserEvent({
            actionName: 'SubCancelFlowSurveyStepShown',
            context: {
              currentPeriod: currentSubscription?.period || '',
              currentUsagePlanId: currentSubscription?.plan?.id || '',
              stripeCouponId: discountOffer?.stripe_coupon_id || '',
              modalStep: 3,
            },
          });
        }}
        handleAcceptOffer={handleAcceptOffer}
      />
    );
  } else if (step === ModalStep.ConfirmOffer && discountOffer) {
    return (
      <ConfirmUpdateStep
        discountOffer={discountOffer}
        currentSubscription={currentSubscription}
        isConfirmLoading={isConfirmLoading}
        onBack={handleBack}
        onConfirm={handleConfirmOffer}
      />
    );
  } else if (step === ModalStep.CancelSurvey) {
    return (
      <CancelSurveyStep
        onBack={handleBack}
        onReasonSelected={handleSurveyReasonSelected}
        isSubmitting={isSurveyLoading}
      />
    );
  } else if (step === ModalStep.SurveyOther) {
    return (
      <SurveyOtherStep
        onBack={handleBack}
        onSubmit={handleSurveyOtherSubmit}
        isLoading={isSurveyLoading}
      />
    );
  }

  return <CancelScheduledStep onClose={onClose} />;
};

export default CancelSubscriptionModalContent;
