import React, {useCallback, useMemo, useRef, useState} from 'react';
import {
  FlatList,
  LayoutChangeEvent,
  NativeScrollEvent,
  NativeSyntheticEvent,
  StyleProp,
  View,
  ViewStyle,
} from 'react-native';
import {useSharedValue} from 'react-native-reanimated';
import {ImageProps} from '@components/_core/Image';
import {Attachment, AttachmentType} from '@interfaces/attachments';
import {ScreenKey} from '@shared/stores/useActivePostsStore';
import {windowDimensions} from '@shared/constants';

import {Footer} from './components/Footer';
import {Header} from './components/Header';
import {MultimediaItem} from './components/MultimediaItem';
import {SCROLL_EVENT_THROTTLE} from './constants';
import {styles} from './styles';
import {calculateMaxHeight} from './utils';

export interface MultimediaContainerProps {
  attachments: Attachment[];
  imageProps?: Omit<ImageProps, 'source'>;
  postId?: number;
  screenKey?: Nullable<ScreenKey>;
  style?: StyleProp<ViewStyle>;
  withAutoPlay?: boolean;
}

export function MultimediaContainer({
  attachments,
  postId,
  screenKey,
  style,
  withAutoPlay,
}: MultimediaContainerProps) {
  const [activeIndex, setActiveIndex] = useState(0);
  const fadeAnimation = useSharedValue(0);
  const showExtraData = attachments.length > 1;
  const flatListRef = useRef<Nullable<FlatList<Attachment>>>(null);

  const onScroll = useCallback(
    ({nativeEvent}: NativeSyntheticEvent<NativeScrollEvent>) => {
      const slide = Math.round(
        nativeEvent.contentOffset.x / nativeEvent.layoutMeasurement.width,
      );
      slide !== activeIndex &&
        slide < attachments.length &&
        setActiveIndex(slide);
    },
    [activeIndex, attachments.length],
  );

  const imageAttachments = useMemo(
    () => attachments.filter(file => file.type === AttachmentType.IMAGE),
    [attachments],
  );

  const [containerWidth, setContainerWidth] = useState(windowDimensions.width);

  const maxHeight = useMemo(
    () =>
      calculateMaxHeight({
        attachments,
        containerWidth,
      }),
    [attachments, containerWidth],
  );

  const onContainerLayout = (e: LayoutChangeEvent) => {
    const w = e.nativeEvent.layout.width;
    if (w && w !== containerWidth) {
      setContainerWidth(w);
      flatListRef.current?.scrollToOffset({
        offset: activeIndex * w,
        animated: false,
      });
    }
  };

  const keyExtractor = useCallback((item: Attachment) => `${item.id}`, []);

  const getItemLayout = useCallback(
    (_: ArrayLike<Attachment> | null | undefined, index: number) => ({
      length: containerWidth,
      offset: containerWidth * index,
      index,
    }),
    [containerWidth],
  );

  const renderItem = useCallback(
    ({item, index}: {item: Attachment; index: number}) => (
      <MultimediaItem
        containerWidth={containerWidth}
        images={imageAttachments}
        isActive={index === activeIndex}
        item={item}
        maxHeight={maxHeight}
        postId={postId}
        screenKey={screenKey}
        withAutoPlay={withAutoPlay}
      />
    ),
    [
      activeIndex,
      containerWidth,
      imageAttachments,
      maxHeight,
      postId,
      screenKey,
      withAutoPlay,
    ],
  );

  return (
    <View onLayout={onContainerLayout} style={[styles.container, style]}>
      <View style={[styles.mediaWrapper, {height: maxHeight}]}>
        {showExtraData && (
          <Header
            attachmentsLength={attachments.length}
            index={activeIndex}
            fadeAnimation={fadeAnimation}
          />
        )}
        <FlatList
          ref={flatListRef}
          horizontal
          pagingEnabled
          data={attachments}
          getItemLayout={containerWidth > 0 ? getItemLayout : undefined}
          keyExtractor={keyExtractor}
          onScroll={onScroll}
          renderItem={renderItem}
          scrollEnabled={attachments.length > 1}
          scrollEventThrottle={SCROLL_EVENT_THROTTLE}
          showsHorizontalScrollIndicator={false}
          style={styles.scrollViewStyle}
        />
      </View>
      {showExtraData && (
        <Footer
          activeIndex={activeIndex}
          attachmentsLength={attachments.length}
        />
      )}
    </View>
  );
}
