import React, {
  useState,
  useRef,
  forwardRef,
  useImperativeHandle,
  useEffect,
} from "react";
import {
  Animated as RNAnimated,
  PanResponder,
  TouchableOpacity,
  Modal,
  KeyboardAvoidingView,
  Platform,
  View,
  StyleSheet,
  BackHandler,
  Easing,
  ViewStyle,
} from "react-native";
import Animated, { FadeIn, FadeInDown } from "react-native-reanimated";

export interface BottomSheetProps {
  height?: number;
  openDuration?: number;
  closeDuration?: number;
  closeOnPressMask?: boolean;
  closeOnPressBack?: boolean;
  draggable?: boolean;
  dragOnContent?: boolean;
  useNativeDriver?: boolean;
  customStyles?: any;
  customModalProps?: object;
  customAvoidingViewProps?: object;
  onOpen?: (() => void) | null;
  onClose?: (() => void) | null;
  children?: React.ReactNode;
  mainContainer?: ViewStyle;
  wrapperColors?: KeyboardAvoidingView["props"]["style"];
}
export interface BottomSheetHandle {
  open: () => void;
  close: () => void;
}

const AnimatedKeyboardAvoidingView =
  Animated.createAnimatedComponent(KeyboardAvoidingView);

export const BottomSheet = forwardRef<BottomSheetHandle, BottomSheetProps>(
  (props, ref) => {
    const {
      height = 260,
      openDuration = 350,
      closeDuration = 300,
      closeOnPressMask = true,
      closeOnPressBack = false,
      draggable = false,
      dragOnContent = false,
      useNativeDriver = false,
      customStyles = {},
      customModalProps = {},
      customAvoidingViewProps = {},
      onOpen = null,
      onClose = null,
      children = <View />,
      mainContainer = {},
      wrapperColors = {},
    } = props;

    const [modalVisible, setModalVisible] = useState(false);
    const animatedHeight = useRef(new RNAnimated.Value(0)).current;
    const pan = useRef(new RNAnimated.ValueXY()).current;

    useEffect(() => {
      const handleBackPress = () => {
        if (modalVisible) {
          handleSetVisible(false);
          return true; // Prevent default back action
        }
        return false;
      };

      const backHandler = BackHandler.addEventListener(
        "hardwareBackPress",
        handleBackPress
      );

      return () => backHandler.remove(); // Ensure removal on unmount
    }, [modalVisible]);

    useImperativeHandle(ref, () => ({
      open: () => handleSetVisible(true),
      close: () => handleSetVisible(false),
    }));

    const createPanResponder = () => {
      return PanResponder.create({
        onStartShouldSetPanResponder: () => draggable,
        onMoveShouldSetPanResponder: (e, gestureState) =>
          draggable && dragOnContent && gestureState.dy > 0,
        onPanResponderMove: (e, gestureState) => {
          gestureState.dy > 0 &&
            RNAnimated.event([null, { dy: pan.y }], { useNativeDriver })(
              e,
              gestureState
            );
        },
        onPanResponderRelease: (e, gestureState) => {
          if (gestureState.dy > 150) {
            handleSetVisible(false);
          } else {
            RNAnimated.spring(pan, {
              toValue: { x: 0, y: 0 },
              useNativeDriver,
              // damping: 0.7,
            }).start();
          }
        },
      });
    };

    const panResponder = useRef(createPanResponder()).current;

    const handleSetVisible = (visible: boolean) => {
      if (visible) {
        setModalVisible(visible);
        if (typeof onOpen === "function") onOpen();

        RNAnimated.timing(animatedHeight, {
          useNativeDriver,
          toValue: height,
          duration: openDuration,
          // easing: Easing.bounce,
        }).start();
      } else {
        RNAnimated.timing(animatedHeight, {
          useNativeDriver,
          toValue: 0,
          duration: closeDuration,
        }).start(() => {
          setModalVisible(visible);
          pan.setValue({ x: 0, y: 0 });
          if (typeof onClose === "function") onClose();
        });
      }
    };

    useEffect(() => {
      if (modalVisible) {
        RNAnimated.timing(animatedHeight, {
          useNativeDriver,
          toValue: height,

          duration: openDuration,
        }).start();
      }
    }, [height, modalVisible]);

    return (
      <Modal
        animationType="fade"
        testID="Modal"
        transparent
        visible={modalVisible}
        // onRequestClose={
        //   closeOnPressBack ? () => handleSetVisible(false) : undefined
        // }
        onRequestClose={() => handleSetVisible(false)}
        {...customModalProps}
        // testID="Modal"
        // transparent
        // visible={modalVisible}
        // onRequestClose={() => handleSetVisible(false)} // Ensure closing on back button
        // {...customModalProps}
      >
        <AnimatedKeyboardAvoidingView
          // entering={FadeInDown.springify().damping(8)}
          testID="KeyboardAvoidingView"
          behavior={Platform.OS === "ios" ? "padding" : "height"}
          style={[styles.wrapper, customStyles.wrapper, wrapperColors]}
          {...customAvoidingViewProps}
        >
          <TouchableOpacity
            testID="TouchableOpacity"
            style={styles.mask}
            activeOpacity={1}
            onPress={
              closeOnPressMask ? () => handleSetVisible(false) : undefined
            }
          />
          <RNAnimated.View
            testID="AnimatedView"
            {...(dragOnContent && panResponder.panHandlers)}
            style={[
              styles.container,
              { transform: pan.getTranslateTransform() },
              { height: animatedHeight },
              customStyles,
              mainContainer,
            ]}
          >
            {draggable && (
              <View
                testID="DraggableView"
                {...(!dragOnContent && panResponder.panHandlers)}
                style={styles.draggableContainer}
              >
                <View
                  testID="DraggableIcon"
                  style={[styles.draggableIcon, customStyles.draggableIcon]}
                />
              </View>
            )}
            {children}
          </RNAnimated.View>
        </AnimatedKeyboardAvoidingView>
      </Modal>
    );
  }
);

const styles = StyleSheet.create({
  wrapper: {
    flex: 1,
    backgroundColor: "#00000077",
  },
  mask: {
    flex: 1,
    backgroundColor: "transparent",
  },
  container: {
    backgroundColor: "#fff",
    width: "100%",
    height: 0,
    overflow: "hidden",
    borderTopRightRadius: 30,
    borderTopLeftRadius: 30,
  },
  draggableContainer: {
    width: "100%",
    alignItems: "center",
    backgroundColor: "transparent",
  },
  draggableIcon: {
    width: 35,
    height: 5,
    borderRadius: 5,
    margin: 10,
    backgroundColor: "#ccc",
  },
});

export default styles;
