import React, {ReactNode, useCallback, useState} from 'react';
import {ImageSourcePropType, Pressable, View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import Modal from 'react-native-modal';
import Animated, {
  Easing,
  useAnimatedStyle,
  useSharedValue,
  withDelay,
  withTiming,
} from 'react-native-reanimated';
import Icon, {IconName} from '@components/Icon';
import {useImageActions} from '@components/Image';
import {COLORS} from '@shared/colors';
import {useTheme} from '@shared/theme';

import {Snackbar} from './components/SnackBar';
import {styles} from './styles';
import {ImageMenu} from './components/ImageMenu';

export interface ImageModalContainerProps {
  source: ImageSourcePropType;
  showZoom: boolean;
  onClose?: () => void;
  children: ReactNode;
}

export function ImageModalContainer({
  source,
  showZoom,
  onClose,
  children,
}: ImageModalContainerProps) {
  const {t} = useTranslation();
  const {spacing} = useTheme();
  const backdropAnimatedOpacity = useSharedValue(0);
  const headerAnimatedOpacity = useSharedValue(0);
  const {top, bottom} = useSafeAreaInsets();
  const [showMenuOptions, setShowMenuOptions] = useState(false);
  const {handleSave, handleShare, snackBarText, clearSnackBar} =
    useImageActions({source});
  const menuOptions = [
    {
      key: 'share',
      label: t('general.share_picture'),
      leftIcon: 'iosShare' as IconName,
    },
    {
      key: 'save',
      label: t('general.save_picture'),
      leftIcon: 'save' as IconName,
    },
    {
      key: 'close',
      label: t('general.cancel'),
      leftIcon: 'doNotDisturb' as IconName,
    },
  ];

  const handleShowMenuOptions = useCallback(() => setShowMenuOptions(true), []);

  const handleHideMenuOptions = useCallback(
    () => setShowMenuOptions(false),
    [],
  );

  const handleOptionPress = useCallback(
    (key: string) => {
      switch (key) {
        case 'share':
          handleShare();
          break;
        case 'save':
          handleSave();
          break;
        case 'close':
          setShowMenuOptions(false);
          break;
      }
    },
    [handleSave, handleShare],
  );

  const onModalWillShow = useCallback(() => {
    backdropAnimatedOpacity.value = withTiming(1, {
      duration: 250,
      easing: Easing.exp,
    });
    headerAnimatedOpacity.value = withDelay(
      500,
      withTiming(1, {duration: 200, easing: Easing.exp}),
    );
  }, [backdropAnimatedOpacity, headerAnimatedOpacity]);

  const onModalWillHide = useCallback(() => {
    backdropAnimatedOpacity.value = 0;
    headerAnimatedOpacity.value = 0;
    clearSnackBar();
  }, [backdropAnimatedOpacity, clearSnackBar, headerAnimatedOpacity]);

  const backdropAnimatedStyle = useAnimatedStyle(() => ({
    opacity: backdropAnimatedOpacity.value,
  }));
  const headerAnimatedStyle = useAnimatedStyle(() => ({
    opacity: headerAnimatedOpacity.value,
  }));

  return (
    <Modal
      isVisible={showZoom}
      style={styles.modal}
      animationIn="zoomIn"
      animationOut="zoomOut"
      hasBackdrop={false}
      onBackButtonPress={onClose}
      onModalWillHide={onModalWillHide}
      onModalWillShow={onModalWillShow}
      useNativeDriver>
      <Animated.View style={[styles.backdrop, backdropAnimatedStyle]} />
      <View
        style={[
          styles.modalContent,
          {
            paddingTop: top,
            paddingBottom: bottom,
          },
        ]}>
        <Animated.View
          style={[styles.header, {top: top + spacing.x1}, headerAnimatedStyle]}>
          <Pressable onPress={onClose} style={styles.headerButton} hitSlop={12}>
            <Icon name="close" size="md" color={COLORS.WHITE} />
          </Pressable>
          <Pressable
            onPress={handleShowMenuOptions}
            style={styles.headerButton}
            hitSlop={12}>
            <Icon name="moreHoriz" size="md" color={COLORS.WHITE} />
          </Pressable>
        </Animated.View>
        {children}
      </View>
      <ImageMenu
        isVisible={showMenuOptions}
        onOptionPress={handleOptionPress}
        onClose={handleHideMenuOptions}
        options={menuOptions}
      />
      <Snackbar show={!!snackBarText} message={snackBarText} />
    </Modal>
  );
}
