import useEmblaCarousel from 'embla-carousel-react';
import { useCallback, useEffect, useState } from 'react';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { twMerge } from 'tailwind-merge';

import { getPriceForPlanAndCurrency } from '@/app/(root)/account/AuraSubscriptions/CurrencySelector';
import { Currency } from '@/app/(root)/account/constants';
import { validateCurrency } from '@/app/(root)/account/utils';
import { AuraSubscriptionCard } from '@/components/card/AuraSubscriptionCard';
import { useCurrencyOptions } from '@/hooks/useCurrencyOptions';
import { useDefaultBillingPeriod } from '@/hooks/useDefaultBillingPeriod';
import { useEligibleDiscounts } from '@/hooks/useEligibleDiscounts';
import { ChevronLeftIcon, ChevronRightIcon } from '@/icons';
import { CHECKOUT_SOURCE } from '@/lib/checkoutSource';
import logWebUserEvent from '@/logging/logWebUserEvent';
import {
  FeatureConfig,
  FeatureKey,
  FeatureUpsellConfig,
  PlanKey,
  UsagePlanSchema,
} from '@/state/sessionStore';
import {
  getUserCurrencyPreference,
  setUserCurrencyPreference,
} from '@/utils/currencyStorage';
import { SubscriptionPeriod } from '@/utils/session';

import { FeatureHeader } from './FeatureHeader';

const { Annual: ANNUAL } = SubscriptionPeriod;

interface FeatureCarouselProps {
  features: FeatureUpsellConfig;
  usagePlanDescriptions: Record<string, any>;
  plans: UsagePlanSchema[];
  getMonthlyPriceForPlanAndCurrency: (
    plan: UsagePlanSchema,
    currency: Currency
  ) => number;
  initialFeatureKey: FeatureKey;
  currentSubscription?: any;
  currentUpsellFeature?: FeatureKey;
  carouselClassName?: string;
}

export const FeaturesAndPlansCarousel = ({
  features,
  plans,
  getMonthlyPriceForPlanAndCurrency,
  initialFeatureKey,
  currentSubscription,
  usagePlanDescriptions,
  currentUpsellFeature,
  carouselClassName,
}: FeatureCarouselProps) => {
  const { t } = useTranslation();
  const { data: eligibleDiscountsResult } = useEligibleDiscounts();
  const defaultPeriod = useDefaultBillingPeriod();
  const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true });

  const enabledFeatures = Object.entries(features)
    .filter(([, feature]) => feature.enabled)
    .map(([key, feature]) => ({ key, feature }));

  const sortedFeatures = initialFeatureKey
    ? enabledFeatures.sort((a, b) =>
        a.key === initialFeatureKey ? -1 : b.key === initialFeatureKey ? 1 : 0
      )
    : enabledFeatures;

  // Get available currencies based on feature flag
  const availableCurrencies = useCurrencyOptions();
  const availableCurrencyValues = availableCurrencies.map((c) => c.value);

  const [selectedCurrency, setSelectedCurrency] = useState<Currency>(
    validateCurrency(getUserCurrencyPreference(), availableCurrencyValues)
  );
  const [period, setPeriod] = React.useState<SubscriptionPeriod>(defaultPeriod);

  // Update period when defaultPeriod changes (e.g., when Statsig loads)
  useEffect(() => {
    setPeriod(defaultPeriod);
  }, [defaultPeriod]);

  const getPlanByKey = (key: PlanKey) => {
    return plans.find((plan) => plan.plan_key === key) || plans[0];
  };

  const [minRequiredPlan, setMinRequiredPlan] = useState<UsagePlanSchema>(
    getPlanByKey(PlanKey.Pro)
  );

  const getPriceForPlan = (
    plan: UsagePlanSchema,
    period: SubscriptionPeriod
  ) => {
    const currency = selectedCurrency;
    if (period === ANNUAL) {
      return (
        getPriceForPlanAndCurrency(plan, currency, SubscriptionPeriod.Annual) /
        12
      );
    }
    return getPriceForPlanAndCurrency(
      plan,
      currency,
      SubscriptionPeriod.Monthly
    );
  };

  const handlePeriodChange = (value: string) => {
    const newPeriod = value as SubscriptionPeriod;
    logWebUserEvent({
      actionName: 'SubscriptionPeriodTabClicked',
      context: {
        period: newPeriod,
        pageUrl: window.location.pathname,
      },
      componentContext: currentUpsellFeature,
    });
    setPeriod(newPeriod);
  };

  const getFeatureDescriptions = (plan: UsagePlanSchema) => {
    const descriptions =
      usagePlanDescriptions?.[plan.plan_key]?.feature_descriptions || [];
    return descriptions.slice(0, 3);
  };

  const goToPrevious = useCallback(() => {
    emblaApi?.scrollPrev();
  }, [emblaApi]);

  const goToNext = useCallback(() => {
    emblaApi?.scrollNext();
  }, [emblaApi]);

  const NavigationButton = ({
    onClick,
    icon: Icon,
    ariaLabel,
    className,
  }: {
    onClick: () => void;
    icon: React.ComponentType<{ className?: string }>;
    ariaLabel: string;
    className?: string;
  }) => (
    <button
      type='button'
      onClick={onClick}
      aria-label={ariaLabel}
      className={twMerge(
        'absolute top-1/2 flex h-8 w-8 -translate-y-1/2 items-center justify-center',
        'transition-[transform,opacity] duration-300 ease-out',
        'z-10',
        className
      )}
    >
      <Icon className='h-6 w-6 text-foreground-primary' />
    </button>
  );

  useEffect(() => {
    const getMinRequiredPlan = ({ feature }: { feature: FeatureConfig }) => {
      if (feature.required_plans.length === 0) {
        return null;
      }
      return feature.required_plans[0] === 'pro'
        ? getPlanByKey(PlanKey.Pro)
        : getPlanByKey(PlanKey.Premier);
    };

    if (!emblaApi) return;

    const onSelect = () => {
      const selectedIndex = emblaApi.selectedScrollSnap();

      if (selectedIndex >= 0 && selectedIndex < sortedFeatures.length) {
        const minRequiredPlan = getMinRequiredPlan({
          feature: sortedFeatures[selectedIndex].feature,
        });
        const selectedPlan = minRequiredPlan || getPlanByKey(PlanKey.Pro);
        setMinRequiredPlan(selectedPlan);
      }
    };

    emblaApi.on('select', onSelect);
    onSelect();

    return () => {
      emblaApi.off('select', onSelect);
    };
  }, [emblaApi, sortedFeatures, plans]);

  return (
    <>
      <div className={twMerge('-mx-6 -mt-6', carouselClassName)}>
        <div className='group/carousel relative flex flex-col bg-transparent'>
          <div
            className='relative w-full flex-1 overflow-x-hidden'
            ref={emblaRef}
          >
            <div className='flex h-full'>
              {sortedFeatures.map(({ feature }, index) => (
                <div key={index} className='h-full min-w-0 flex-[0_0_100%]'>
                  <FeatureHeader feature={feature} />
                </div>
              ))}
            </div>
          </div>
          {sortedFeatures.length > 1 && (
            <>
              <NavigationButton
                onClick={goToPrevious}
                icon={ChevronLeftIcon}
                ariaLabel={t('cta.prev')}
                className='left-1 sm:left-2'
              />
              <NavigationButton
                onClick={goToNext}
                icon={ChevronRightIcon}
                ariaLabel={t('cta.next')}
                className='right-1 sm:right-2'
              />
            </>
          )}
        </div>
      </div>
      <div className='mt-5 mb-5'>
        <AuraSubscriptionCard
          key={minRequiredPlan.id}
          plan={minRequiredPlan}
          price={getPriceForPlan(minRequiredPlan, period)}
          priceBeforeDiscount={getMonthlyPriceForPlanAndCurrency(
            minRequiredPlan,
            selectedCurrency
          )}
          period={period}
          billed={period === ANNUAL ? 'yearly' : 'monthly'}
          features={getFeatureDescriptions(minRequiredPlan)}
          currentSubscription={currentSubscription}
          planDescription={usagePlanDescriptions[minRequiredPlan.plan_key]}
          showPlanPeriodToggle={true}
          onPeriodChange={handlePeriodChange}
          buttonWrapperClassName='[&_button]:h-12 [&_button]:text-sm [&_button]:flex [&_button]:items-center [&_button]:justify-center'
          gapClassName='gap-6'
          showBadge={false}
          hideSavingSubtitle={true}
          checkoutSource={CHECKOUT_SOURCE.UPSELL_MODAL}
          currentUpsellFeature={currentUpsellFeature}
          selectedCurrency={selectedCurrency}
          showCurrencySelector={true}
          highlightPlans={[PlanKey.Pro, PlanKey.Premier]}
          onCurrencyChange={(currency) => {
            const validatedCurrency = validateCurrency(
              currency,
              availableCurrencyValues
            );
            setSelectedCurrency(validatedCurrency);
            setUserCurrencyPreference(validatedCurrency);
          }}
          discountDetails={
            eligibleDiscountsResult?.eligible_discounts[
              minRequiredPlan.plan_key
            ]?.[period]
          }
        />
      </div>
    </>
  );
};
