import {memo, ReactNode, useCallback, useMemo, useState} from 'react';
import {LayoutChangeEvent, ScrollView} from 'react-native';
import MaskedView from '@react-native-masked-view/masked-view';
import {Gradient, GradientProps} from '@components/_core';
import {ScrollEvent} from '@interfaces/generic';
import {useTheme} from '@shared/theme';

import {styles} from './styles';

export const MASK_TRANSPARENT_COLOR = 'rgba(255, 255, 255, 0)';
interface Props {
  children: ReactNode;
}

function MaskedScrollViewContainerComponent({children}: Props) {
  const {theme} = useTheme();
  const [scrollInfo, setScrollInfo] = useState({
    scrollX: 0,
    contentWidth: 0,
    containerWidth: 0,
  });

  // Calculate scroll state
  const scrollState = useMemo(() => {
    const {scrollX, contentWidth, containerWidth} = scrollInfo;
    const hasScrollContent = contentWidth > containerWidth;
    const isAtEnd = scrollX >= contentWidth - containerWidth - 5;

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

  // Dynamic mask gradient based on scroll state - only right side fade
  const maskGradient: {
    colors: GradientProps['colors'];
    locations: GradientProps['locations'];
  } = useMemo(() => {
    const {canScrollRight} = scrollState;

    if (canScrollRight) {
      return {
        colors: [
          theme.background.layout.tertiary,
          theme.background.layout.tertiary,
          theme.background.layout.tertiary,
          MASK_TRANSPARENT_COLOR,
        ],
        locations: [0, 0.8, 0.9, 1],
      };
    }

    // When no fade is needed, use a single color or two colors with valid locations
    return {
      colors: [
        theme.background.layout.tertiary,
        theme.background.layout.tertiary,
      ],
      locations: [0, 1],
    };
  }, [scrollState, theme.background.layout.tertiary]);

  const onScroll = useCallback((event: ScrollEvent) => {
    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,
    }));
  }, []);

  return (
    <MaskedView
      style={styles.maskedContainer}
      maskElement={
        <Gradient
          colors={maskGradient.colors}
          locations={maskGradient.locations}
          start={{x: 0, y: 0}}
          end={{x: 1, y: 0}}
          style={styles.maskedContainer}
        />
      }>
      <ScrollView
        bounces={false}
        showsHorizontalScrollIndicator={false}
        horizontal
        contentContainerStyle={styles.content}
        onScroll={onScroll}
        onContentSizeChange={onContentSizeChange}
        onLayout={onLayout}
        scrollEventThrottle={16}>
        {children}
      </ScrollView>
    </MaskedView>
  );
}

export const MaskedScrollViewContainer = memo(
  MaskedScrollViewContainerComponent,
);
