'use client';

import { useAuth, useClerk } from '@clerk/nextjs';
import { useState } from 'react';

import {
  Currency,
  SUBSCRIPTION_PAGE_VERSIONS,
} from '@/app/(root)/account/constants';
import { ButtonVariant } from '@/components/button/Button';
import { AXON_ITEM_CATEGORY_ID } from '@/components/ga4/constants';
import {
  createAxonItemVariantIdForSubscription,
  useAxon,
} from '@/components/ga4/useAxon';
import AuraModal from '@/components/modal/AuraModal';
import SpinnerSVG from '@/components/svg/SpinnerSVG';
import { toast } from '@/components/toast/Toast';
import { useSproutTracking } from '@/hooks/useSproutTracking';
import { useApiClient } from '@/lib/apiClient';
import { CHECKOUT_SOURCE, type CheckoutSource } from '@/lib/checkoutSource';
import logWebUserEvent from '@/logging/logWebUserEvent';
import {
  CheckoutSession,
  FeatureKey,
  PlanKey,
  SubscriptionInfo,
  UsagePlanSchema,
} from '@/state/sessionStore';
import { CtaButtons } from '@/state/sessionStore';
import { SubscriptionPeriod } from '@/utils/session';
import {
  SubscriptionAction,
  getSubscriptionAction,
} from '@/utils/subscriptionActions';
import { getClerkSignInRedirectProps } from '@/utils/utils';

import { getPriceForPlanAndCurrency } from './CurrencySelector';
import CancelSubscriptionModalContent from './modals/CancelSubscriptionModalContent';
import ChangeCommitmentModalContent from './modals/ChangeCommitmentModalContent';
import DowngradeSubscriptionModalContent from './modals/DowngradeSubscriptionModalContent';
import UpgradeSubscriptionModalContent from './modals/UpgradeSubscriptionModalContent';
import { ModalButton } from './modals/shared/ModalButton';

/**
 * Creates a map of subscription actions to their localized button labels.
 * Falls back to English defaults if translations are not available.
 */
const createLabelMap = (
  ctaButtons?: CtaButtons | null
): Record<SubscriptionAction, string> => ({
  [SubscriptionAction.ChangeCommitment]:
    ctaButtons?.change_commitment?.text || 'Change Commitment',
  [SubscriptionAction.ChangeCommitmentDelayedOnly]:
    ctaButtons?.change_commitment?.text || 'Change Commitment',
  [SubscriptionAction.CurrentPlan]:
    ctaButtons?.current_plan?.text || 'Current Plan',
  [SubscriptionAction.Subscribe]: ctaButtons?.subscribe?.text || 'Subscribe',
  [SubscriptionAction.Upgrade]: ctaButtons?.upgrade?.text || 'Upgrade',
  [SubscriptionAction.UpgradeDelayedOnly]:
    ctaButtons?.upgrade?.text || 'Upgrade',
  [SubscriptionAction.Cancel]: ctaButtons?.cancel_plan?.text || 'Cancel Plan',
  [SubscriptionAction.Downgrade]: ctaButtons?.downgrade?.text || 'Downgrade',
  [SubscriptionAction.Inactive]:
    ctaButtons?.cancel_scheduled?.text || 'Cancel Scheduled',
  [SubscriptionAction.Unavailable]:
    ctaButtons?.not_available?.text || 'Not Available',
});

export const ChangePlanButton = ({
  currentSubscription,
  targetPlan,
  period,
  highlightPlans,
  checkoutSource,
  currentUpsellFeature,
  selectedCurrency,
  ctaButtons,
}: {
  currentSubscription: SubscriptionInfo | null;
  targetPlan: UsagePlanSchema;
  period: SubscriptionPeriod;
  highlightPlans?: PlanKey[];
  checkoutSource?: CheckoutSource;
  currentUpsellFeature?: FeatureKey;
  selectedCurrency: Currency;
  ctaButtons?: CtaButtons | null;
}) => {
  const apiClient = useApiClient();
  const { isSignedIn } = useAuth();
  const clerk = useClerk();
  const {
    publishBeginCheckoutEvent: publishAxonBeginCheckoutEvent,
    publishAddToCartEvent: publishAxonAddToCartEvent,
  } = useAxon();
  const { getSproutAffiliateIdForApi } = useSproutTracking();

  const [isModalOpen, setIsModalOpen] = useState(false);
  const [modalIcon, setModalIcon] = useState<React.ReactElement | undefined>(
    undefined
  );
  const [isLoading, setIsLoading] = useState(false);
  const [modalAction, setModalAction] = useState<SubscriptionAction | null>(
    null
  );
  const currentPlan = currentSubscription?.plan;
  const action = getSubscriptionAction(
    currentSubscription || undefined,
    targetPlan,
    period
  );
  const activeAction = modalAction || action;
  const labelMap = createLabelMap(ctaButtons);

  const disabled =
    [
      SubscriptionAction.CurrentPlan,
      SubscriptionAction.Inactive,
      SubscriptionAction.Unavailable,
    ].includes(action) || isLoading;
  const isHighlightedPlan = highlightPlans?.includes(
    targetPlan.plan_key as PlanKey
  );
  const variant =
    [
      SubscriptionAction.Subscribe,
      SubscriptionAction.Upgrade,
      SubscriptionAction.UpgradeDelayedOnly,
    ].includes(action) && isHighlightedPlan
      ? ButtonVariant.Primary
      : ButtonVariant.Glass;

  const subscribeButtonComponentContext = currentUpsellFeature || '';

  // Tooltip text for unavailable actions
  const getTooltipText = () =>
    action === SubscriptionAction.Unavailable
      ? 'Please cancel your plan and re-subscribe to access.'
      : undefined;

  const handleSubscribe = async () => {
    if (isLoading) return;
    setIsLoading(true);

    try {
      logWebUserEvent({
        actionName: 'SubscribeButtonClicked',
        context: {
          usagePlanId: targetPlan?.id,
          period,
          currency: selectedCurrency,
          isLoggedIn: Boolean(isSignedIn),
          checkoutSource: checkoutSource || CHECKOUT_SOURCE.ACCOUNT_PAGE,
        },
        componentContext: subscribeButtonComponentContext,
      });
      const currency = selectedCurrency;
      const price = getPriceForPlanAndCurrency(targetPlan, currency, period);

      // Validate price before proceeding with checkout
      if (Number.isNaN(price)) {
        console.error(
          `Price not available for currency ${currency} and period ${period}`
        );
        toast({
          title: 'Pricing Unavailable',
          description: `${targetPlan.name} pricing is not available in ${currency}. Please select a different currency or plan.`,
          status: 'error',
          duration: 5000,
          isClosable: true,
        });
        return;
      }

      const usdPrice =
        period === SubscriptionPeriod.Monthly
          ? targetPlan.monthly_price_usd
          : targetPlan.annual_price_usd;

      const axonItem = {
        item_variant_id: createAxonItemVariantIdForSubscription(
          targetPlan.plan_key,
          period
        ),
        item_id: targetPlan.plan_key,
        item_name: targetPlan.name,
        price: usdPrice,
        quantity: 1,
        item_category_id: AXON_ITEM_CATEGORY_ID,
      };

      publishAxonAddToCartEvent({
        currency: Currency.USD,
        value: usdPrice,
        items: [axonItem],
      });

      publishAxonBeginCheckoutEvent({
        currency: Currency.USD,
        value: usdPrice,
        items: [axonItem],
      });

      const sproutAffiliateId = getSproutAffiliateIdForApi(); // passes transaction id to backend for content creator affiliate link tracking
      const { data } = await apiClient.POST('/api/billing/create-session/', {
        body: {
          plan_key: targetPlan.plan_key,
          period,
          checkout_source: checkoutSource,
          current_upsell_feature: currentUpsellFeature,
          sprout_affiliate_id: sproutAffiliateId,
          currency: selectedCurrency,
        },
      });

      const sessionData = data as CheckoutSession;
      if (sessionData?.url) {
        window.location.href = sessionData.url;
      }
    } finally {
      setIsLoading(false);
    }
  };

  const handleClick = () => {
    if (disabled) return;

    // If user is not signed in and trying to subscribe, open sign up modal with redirect
    if (!isSignedIn) {
      if (action === SubscriptionAction.Subscribe) {
        const source = checkoutSource || CHECKOUT_SOURCE.SPLASH_PAGE;
        logWebUserEvent({
          actionName: 'SubscribeButtonClicked',
          context: {
            usagePlanId: targetPlan?.id,
            period,
            currency: selectedCurrency,
            isLoggedIn: Boolean(isSignedIn),
            checkoutSource: source,
          },
          componentContext: '',
        });

        const redirectUrl = `/redirect?plan_key=${targetPlan.plan_key}&period=${period}&checkout_source=${source}&currency=${selectedCurrency}`;
        clerk.openSignIn({
          withSignUp: true,
          ...getClerkSignInRedirectProps(redirectUrl),
        });
      }
      return;
    }

    if (action === SubscriptionAction.Subscribe) {
      handleSubscribe();
    } else {
      if (action === SubscriptionAction.Cancel) {
        logWebUserEvent({
          actionName: 'CancelSubscriptionButtonClicked',
          context: {
            currentUsagePlanId: currentPlan?.id || '',
            currentPeriod: currentSubscription?.period || '',
            subPageVersion: SUBSCRIPTION_PAGE_VERSIONS.aura,
            currency: selectedCurrency,
          },
        });
      }

      setModalAction(action);
      setIsModalOpen(true);
    }
  };

  const handleModalClose = () => {
    setIsModalOpen(false);
    setModalAction(null);
  };

  const modalProps = currentSubscription
    ? {
        currentSubscription,
        targetPlan,
        period,
        onClose: handleModalClose,
        setIcon: setModalIcon,
        selectedCurrency,
        action: activeAction,
      }
    : null;

  return (
    <>
      <ModalButton
        variant={variant}
        disabled={disabled}
        onClick={handleClick}
        icon={isLoading ? <SpinnerSVG className='fill-black' /> : undefined}
        tooltip={getTooltipText()}
      >
        {isLoading ? 'Redirecting...' : labelMap[action]}
      </ModalButton>

      {modalProps && (
        <AuraModal
          open={isModalOpen}
          onOpenChange={setIsModalOpen}
          title={labelMap[activeAction]}
          icon={modalIcon}
        >
          {activeAction === SubscriptionAction.ChangeCommitment ||
          activeAction === SubscriptionAction.ChangeCommitmentDelayedOnly ? (
            <ChangeCommitmentModalContent {...modalProps} />
          ) : activeAction === SubscriptionAction.Upgrade ||
            activeAction === SubscriptionAction.UpgradeDelayedOnly ? (
            <UpgradeSubscriptionModalContent {...modalProps} />
          ) : activeAction === SubscriptionAction.Downgrade ? (
            <DowngradeSubscriptionModalContent {...modalProps} />
          ) : (
            <CancelSubscriptionModalContent {...modalProps} />
          )}
        </AuraModal>
      )}
    </>
  );
};
