import React, {ReactNode, useCallback, useState} from 'react';
import {View} from 'react-native';
import {ImageSource} from 'expo-image';
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 {
  IconDeviceFloppy,
  IconDots,
  IconShare2,
  IconX,
} from '@tabler/icons-react-native';
import {IconButton} from '@components/_HuGo/Button';
import {useTheme} from '@shared/theme';

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

const MENU_OPTIONS = [
  {
    key: 'share',
    label: 'general.share_picture',
    Icon: IconShare2,
  },
  {
    key: 'save',
    label: 'general.save_picture',
    Icon: IconDeviceFloppy,
  },
];

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

export function ImageModalContainer({
  children,
  onClose,
  showZoom,
  source,
  showOptionsMenu = true,
}: ImageModalContainerProps) {
  const {spacing} = useTheme();
  const backdropAnimatedOpacity = useSharedValue(0);
  const headerAnimatedOpacity = useSharedValue(0);
  const {top, bottom} = useSafeAreaInsets();
  const [showMenuOptions, setShowMenuOptions] = useState(false);
  const {onSaveImage, onShareImage, snackBarText, clearSnackBar} =
    useImageActions({source});

  const onShowMenuOptions = useCallback(() => setShowMenuOptions(true), []);
  const onHideMenuOptions = useCallback(() => setShowMenuOptions(false), []);

  const onOptionPress = useCallback(
    (key: string) => {
      switch (key) {
        case 'share':
          onShareImage();
          break;
        case 'save':
          onSaveImage();
          break;
      }
    },
    [onSaveImage, onShareImage],
  );

  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
      useNativeDriver
      animationIn="zoomIn"
      animationOut="zoomOut"
      hasBackdrop={false}
      isVisible={showZoom}
      onBackButtonPress={onClose}
      onModalWillHide={onModalWillHide}
      onModalWillShow={onModalWillShow}
      statusBarTranslucent
      style={styles.modal}>
      <Animated.View style={[styles.backdrop, backdropAnimatedStyle]} />
      <View
        style={[styles.modalContent, {paddingTop: top, paddingBottom: bottom}]}>
        <Animated.View
          style={[styles.header, {top: top + spacing.x1}, headerAnimatedStyle]}>
          <IconButton
            appearance="dark"
            hitSlop={spacing['x1.5']}
            Icon={IconX}
            onPress={onClose}
            variant="flat"
            style={styles.headerButton}
          />
          {showOptionsMenu && (
            <IconButton
              appearance="dark"
              hitSlop={spacing['x1.5']}
              Icon={IconDots}
              onPress={onShowMenuOptions}
              variant="flat"
              style={styles.headerButton}
            />
          )}
        </Animated.View>
        {children}
      </View>
      <ImageMenu
        isVisible={showMenuOptions}
        onClose={onHideMenuOptions}
        onOptionPress={onOptionPress}
        options={MENU_OPTIONS}
      />
      <Snackbar show={!!snackBarText} message={snackBarText} />
    </Modal>
  );
}
