import React, {
  memo,
  PropsWithChildren,
  useEffect,
  useRef,
  useState,
} from 'react';
import {InteractionManager, Pressable, View} from 'react-native';
import {Portal} from '@gorhom/portal';
import {BlurView} from 'expo-blur';
import {EaseView} from 'react-native-ease';
import {useBackHandler} from '@hooks/useBackHandler';
import {CHAT_PORTAL_HOST_NAME} from '@modules/chats/constants';
import {isAndroid} from '@shared/utils';

import {styles} from './styles';

interface Props extends PropsWithChildren {
  isVisible: boolean;
  onClose: () => void;
}

const FADE_DURATION = 140;
const BLUR_BACKGROUND = 'rgba(0,0,0,0.3)';

const ContextModalComponent = ({children, onClose, isVisible}: Props) => {
  const [shouldRender, setShouldRender] = useState(false);
  const interactiveHandlerRef = useRef<Nullable<number>>(null);
  const timerRef = useRef<Nullable<NodeJS.Timeout>>(null);

  const clearTimerRef = () => {
    if (timerRef.current) {
      clearTimeout(timerRef.current);
      timerRef.current = null;
    }
  };

  const clearInteractiveHandler = () => {
    if (interactiveHandlerRef.current) {
      InteractionManager.clearInteractionHandle(interactiveHandlerRef.current);
      interactiveHandlerRef.current = null;
    }
    clearTimerRef();
  };

  const closeAnimationFinished = () => {
    setShouldRender(false);
    clearInteractiveHandler();
  };

  // Create an interactive handler to be able to wait for the animation to finish in other components
  // by using InteractionManager.runAfterInteractions.
  const createInteractionHandle = () => {
    interactiveHandlerRef.current =
      InteractionManager.createInteractionHandle();

    clearTimerRef();
    // Just in case, if in some cases if won't be cleared, we clear it after the animation duration.
    timerRef.current = setTimeout(() => {
      clearInteractiveHandler();
    }, FADE_DURATION + 150);
  };

  useEffect(() => {
    if (isVisible) {
      setShouldRender(true);
    } else {
      createInteractionHandle();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [isVisible]);

  useEffect(() => {
    // Cleanup on unmount
    return clearInteractiveHandler;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  useBackHandler(() => {
    if (!shouldRender) {
      return false;
    }

    onClose();
    return true;
  });

  if (!shouldRender) {
    return null;
  }

  return (
    <Portal hostName={CHAT_PORTAL_HOST_NAME.messages}>
      <Pressable
        accessible={false}
        style={[styles.fill, styles.container]}
        onPress={onClose}>
        <EaseView
          accessible={false}
          initialAnimate={{opacity: 0}}
          animate={{opacity: isVisible && shouldRender ? 1 : 0}}
          onTransitionEnd={() => {
            if (!isVisible) closeAnimationFinished();
          }}
          transition={{
            type: 'timing',
            duration: FADE_DURATION,
          }}
          style={[styles.fill]}>
          <BlurView
            accessible={false}
            style={[
              styles.fill,
              isAndroid
                ? {
                    backgroundColor: BLUR_BACKGROUND,
                  }
                : {},
            ]}
            intensity={40}
            blurReductionFactor={6}
          />
          <View style={[styles.fill, styles.container]}>{children}</View>
        </EaseView>
      </Pressable>
    </Portal>
  );
};

export const ContextModal = memo(ContextModalComponent);
