import React, {useState, useRef, useCallback, ComponentProps} from 'react';
import {ListRenderItem, View, ViewToken} from 'react-native';
import {useTranslation} from 'react-i18next';
import {Image} from 'expo-image';
import {FlatList} from 'react-native-gesture-handler';
import Video, {ResizeMode} from '@components/_core/RNVideo';
import {Typography} from '@components/_core/Typography';
import {Dialog, DialogProps} from '@components/_HuGo/Dialog';
import {windowDimensions} from '@shared/constants';

import {PaginationDot} from './components/PaginationDot';
import {styles} from './styles';

const viewabilityConfig = {viewAreaCoveragePercentThreshold: 60};
const {width} = windowDimensions;

export interface CoachmarkStep {
  key?: string;
  title?: string;
  description: string;
  video?: ComponentProps<typeof Video>['source'];
  image?: ComponentProps<typeof Image>['source'];
}

const keyExtractor = (_: CoachmarkStep, index: number) => {
  return `new-feature-step-${index}`;
};

const renderItem: ListRenderItem<CoachmarkStep> = ({item: step}) => {
  return (
    <View>
      <View style={{width}}>
        {step.video && (
          <Video
            style={styles.multimedia}
            source={step.video}
            resizeMode={ResizeMode.COVER}
            repeat
            muted
            controls={false}
          />
        )}
        {step.image && (
          <Image
            source={step.image}
            contentFit="cover"
            style={styles.multimedia}
          />
        )}
      </View>
      <View style={[{width}, styles.content]}>
        {step.title && <Typography weight="semiBold">{step.title}</Typography>}
        <Typography variant="xs">{step.description}</Typography>
      </View>
    </View>
  );
};

interface CoachmarkProps extends Omit<DialogProps, 'children'> {
  steps: CoachmarkStep[];
}

export function Coachmark({
  steps,
  contentStyle,
  ...dialogProps
}: CoachmarkProps) {
  const {t} = useTranslation();
  const [currentStep, setCurrentStep] = useState(0);
  const contentScrollRef = useRef<FlatList>(null);

  const scrollToStep = useCallback((step: number) => {
    contentScrollRef.current?.scrollToIndex({index: step, animated: true});
  }, []);

  const onViewableItemsChanged = useCallback(
    (info: {
      viewableItems: Array<ViewToken<CoachmarkStep>>;
      changed: Array<ViewToken<CoachmarkStep>>;
    }) => {
      if (info.viewableItems.length > 0) {
        const index = info.viewableItems[0].index || 0;
        setCurrentStep(index);
      }
    },
    [],
  );

  const onNextStep = useCallback(() => {
    if (currentStep >= steps.length - 1) {
      dialogProps?.onClose?.();
      return;
    }
    const nextStep = currentStep + 1;
    setCurrentStep(nextStep);
    scrollToStep(nextStep);
  }, [currentStep, dialogProps, scrollToStep, steps.length]);

  const onGoBack = useCallback(() => {
    if (currentStep > 0) {
      const prevStep = currentStep - 1;
      setCurrentStep(prevStep);
      scrollToStep(prevStep);
    }
  }, [currentStep, scrollToStep]);

  const isLastStep = currentStep === steps.length - 1;
  const isSingleStep = steps.length === 1;

  return (
    <Dialog
      style={styles.dialogContainer}
      headerStyle={styles.header}
      contentStyle={[styles.dialog, contentStyle]}
      withBackButton={currentStep > 0}
      titleNumberOfLines={2}
      onGoBack={onGoBack}
      title={t('service_management.new_feature.title')}
      footer={{
        primaryButton: {
          text: isSingleStep
            ? t('general.got_it')
            : isLastStep
            ? t('general.finish')
            : t('general.next'),
          onPress: onNextStep,
        },
      }}
      {...dialogProps}>
      <View style={styles.listContainer}>
        <FlatList
          horizontal
          pagingEnabled
          data={steps}
          ref={contentScrollRef}
          snapToInterval={width}
          decelerationRate={'fast'}
          viewabilityConfig={viewabilityConfig}
          onViewableItemsChanged={onViewableItemsChanged}
          keyExtractor={keyExtractor}
          showsHorizontalScrollIndicator={false}
          renderItem={renderItem}
          scrollEnabled={!isSingleStep}
        />
        <View pointerEvents="none" style={styles.paginationContainer}>
          {!isSingleStep &&
            steps.map((_, index) => (
              <PaginationDot key={index} isActive={index === currentStep} />
            ))}
        </View>
      </View>
    </Dialog>
  );
}
