import React, {forwardRef, useCallback, useMemo, useState} from 'react';
import {
  FlatList,
  LayoutChangeEvent,
  NativeScrollEvent,
  NativeSyntheticEvent,
  StyleProp,
  View,
  ViewStyle,
} from 'react-native';
import MaskedView from '@react-native-masked-view/masked-view';
import {IconX} from '@tabler/icons-react-native';
import {
  Pressable,
  Typography,
  Avatar,
  Gradient,
  GradientProps,
} from '@components';
import {ChatUser} from '@modules/chats/interfaces';
import {getUserAvatar} from '@modules/chats/utils';
import {useTheme} from '@shared/theme';

import {styles} from './styles';

interface Props {
  users: ChatUser[];
  style?: StyleProp<ViewStyle>;
  onPress?: (user: ChatUser) => void;
}

const keyExtractor = (item: ChatUser) => `${item.id}`;
const MASK_TRANSPARENT_COLOR = 'transparent';

const HorizontalUsersDisplayer = forwardRef<FlatList, Props>(
  ({users, style, onPress}, ref) => {
    const {theme, iconSizes} = useTheme();
    const [scrollInfo, setScrollInfo] = useState({
      scrollX: 0,
      contentWidth: 0,
      containerWidth: 0,
    });

    const onScroll = useCallback(
      (event: NativeSyntheticEvent<NativeScrollEvent>) => {
        const {contentOffset} = event.nativeEvent;
        setScrollInfo(current => ({
          ...current,
          scrollX: contentOffset.x,
        }));
      },
      [],
    );

    const onContentSizeChange = useCallback((contentWidth: number) => {
      setScrollInfo(current => ({
        ...current,
        contentWidth,
      }));
    }, []);

    const onLayout = useCallback((event: LayoutChangeEvent) => {
      const {width} = event.nativeEvent.layout;
      setScrollInfo(current => ({
        ...current,
        containerWidth: width,
      }));
    }, []);

    const scrollState = useMemo(() => {
      const {scrollX, contentWidth, containerWidth} = scrollInfo;
      const hasScrollContent = contentWidth > containerWidth;
      const isAtStart = scrollX <= 5;
      const isAtEnd = scrollX >= contentWidth - containerWidth - 5;

      return {
        hasScrollContent,
        canScrollLeft: hasScrollContent && !isAtStart,
        canScrollRight: hasScrollContent && !isAtEnd,
      };
    }, [scrollInfo]);

    const maskGradient: {
      colors: GradientProps['colors'];
      locations: GradientProps['locations'];
    } = useMemo(() => {
      const {canScrollLeft, canScrollRight} = scrollState;
      const opaqueColor = theme.background.layout.tertiary;

      if (canScrollLeft && canScrollRight) {
        return {
          colors: [
            MASK_TRANSPARENT_COLOR,
            opaqueColor,
            opaqueColor,
            MASK_TRANSPARENT_COLOR,
          ],
          locations: [0, 0.08, 0.92, 1],
        };
      }

      if (canScrollRight) {
        return {
          colors: [opaqueColor, opaqueColor, MASK_TRANSPARENT_COLOR],
          locations: [0, 0.92, 1],
        };
      }

      if (canScrollLeft) {
        return {
          colors: [MASK_TRANSPARENT_COLOR, opaqueColor, opaqueColor],
          locations: [0, 0.08, 1],
        };
      }

      return {
        colors: [opaqueColor, opaqueColor],
        locations: [0, 1],
      };
    }, [scrollState, theme.background.layout.tertiary]);

    const renderItem = useCallback(
      ({item, index}: {item: ChatUser; index: number}) => {
        const onInternalPress = () => {
          onPress?.(item);
        };
        const isFirstItem = index === 0;
        const isLastItem = index === users.length - 1;
        const avatar = getUserAvatar(item.hu_data.member);

        return (
          <Pressable
            onPress={onInternalPress}
            style={[
              styles.itemContainer,
              isFirstItem && styles.firstItemContainer,
              isLastItem && styles.lastItemContainer,
            ]}>
            <View style={styles.internalItemContainer}>
              <View>
                <Avatar {...avatar} />
                <View
                  style={[
                    styles.internalItemXContainer,
                    {backgroundColor: theme.action.background.neutral.hover},
                  ]}>
                  <IconX
                    color={theme.text.neutral.default}
                    size={iconSizes.x3}
                  />
                </View>
              </View>
              <Typography
                variant="xxxs"
                color={theme.text.neutral.lighter}
                numberOfLines={1}
                style={styles.internalItemTitle}>
                {avatar.name}
              </Typography>
            </View>
          </Pressable>
        );
      },
      // eslint-disable-next-line react-hooks/exhaustive-deps
      [onPress, users.length],
    );

    return (
      <View style={style}>
        <View
          style={[
            {
              backgroundColor: theme.background.elements.default,
              borderColor: theme.border.neutral.default,
            },
            styles.listContainer,
          ]}
          onLayout={onLayout}>
          <MaskedView
            maskElement={
              <Gradient
                colors={maskGradient.colors}
                locations={maskGradient.locations}
                start={{x: 0, y: 0}}
                end={{x: 1, y: 0}}
                style={styles.maskGradient}
              />
            }>
            <FlatList
              ref={ref}
              data={users}
              horizontal
              renderItem={renderItem}
              keyExtractor={keyExtractor}
              showsHorizontalScrollIndicator={false}
              contentContainerStyle={styles.listContent}
              bounces={false}
              onScroll={onScroll}
              onContentSizeChange={onContentSizeChange}
              scrollEventThrottle={16}
            />
          </MaskedView>
        </View>
      </View>
    );
  },
);

export default HorizontalUsersDisplayer;
