import type { ReactNode } from 'react';
import React, { useCallback, useEffect } from 'react';
import type {
  LayoutChangeEvent,
  StyleProp,
  ViewProps,
  ViewStyle,
} from 'react-native';
import { LayoutAnimation, Platform, UIManager } from 'react-native';
import { usePrevious } from '../../utils/hooks';
import {
  StyledChildWrapper,
  StyledHiddenWrapper,
  StyledWrapper,
} from './StyledCollapse';

export interface CollapseProps extends ViewProps {
  /*
   * The collapse's content.
   */
  children: ReactNode;
  /**
   * Whether the component is open or closed.
   */
  open?: boolean;
  /**
   * Additional style.
   */
  style?: StyleProp<ViewStyle>;
  /**
   * Testing id of the component.
   */
  testID?: string;
}

if (Platform.OS === 'android') {
  if (UIManager.setLayoutAnimationEnabledExperimental) {
    UIManager.setLayoutAnimationEnabledExperimental(true);
  }
}

const Collapse = ({
  open = false,
  children,
  testID,
  style,
  onLayout,
}: CollapseProps) => {
  const [contentHeight, setContentHeight] = React.useState<number>(0);
  const [componentMounted, setComponentMounted] =
    React.useState<boolean>(false);

  const previousOpenState = usePrevious(open);

  useEffect(() => {
    if (
      ((open !== previousOpenState && previousOpenState !== undefined) ||
        open) &&
      componentMounted
    ) {
      LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
    }
  }, [open, previousOpenState, contentHeight]);

  const fetchMaxHeight = useCallback(({ height }: { height: number }) => {
    setContentHeight(height);
  }, []);

  const onCollapseLayout = useCallback((e: LayoutChangeEvent) => {
    setComponentMounted(true);

    onLayout?.(e);
  }, []);

  return (
    <StyledWrapper
      style={{
        height: open ? contentHeight : 0,
      }}
      onLayout={onCollapseLayout}
      testID={testID}
    >
      <StyledHiddenWrapper>
        <StyledChildWrapper
          onLayout={(event) => fetchMaxHeight(event.nativeEvent.layout)}
          style={style}
        >
          {children}
        </StyledChildWrapper>
      </StyledHiddenWrapper>
    </StyledWrapper>
  );
};

export default Collapse;
