import React, { forwardRef, ReactElement, useCallback, useEffect, useState } from 'react';

import Animated, { AnimatedStyle, Easing, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';

import { Container, ContainerRef } from '@cleartrip/ct-design-container';
import useIsomorphicEffect from '@cleartrip/ct-design-use-isomorphic-effect';

import type { IAccordionProps } from './type';
import staticStyles from './style';
import { ViewStyle } from 'react-native';

const ANIMATION_DURATION = 300;

const AccordionV2 = forwardRef(
  (
    {
      expanded = false,
      label,
      onClick,
      children,
      expandIcon,
      disabled = false,
      styleConfig,
      isWrappedInAccordionGroup = false,
      onAccordionGroupClick,
    }: IAccordionProps,
    ref: React.ForwardedRef<ContainerRef>,
  ): ReactElement => {
    const { childrenContainer = [], icon = [], label: labelStyle = [], root = [] } = styleConfig || {};

    const [isExpanded, setIsExpanded] = useState<boolean>(expanded);
    const [rootContainerHeight, setRootContainerHeight] = useState<number | undefined>();
    const [childContainerHeight, setChildContainerHeight] = useState<number | undefined>();

    useIsomorphicEffect(() => {
      setIsExpanded(expanded);
    }, [expanded]);

    const rotation = useSharedValue(expanded ? 180 : 0);
    const height = useSharedValue<number | undefined>(expanded ? rootContainerHeight : 0);

    useEffect(() => {
      rotation.value = withTiming(isExpanded ? 180 : 0, {
        duration: ANIMATION_DURATION,
      });

      if (rootContainerHeight !== undefined && childContainerHeight !== undefined) {
        height.value = withTiming(isExpanded ? rootContainerHeight : rootContainerHeight - childContainerHeight, {
          duration: ANIMATION_DURATION,
          easing: Easing.inOut(Easing.ease),
        });
      }
    }, [isExpanded, rootContainerHeight, childContainerHeight, rotation, height]);

    const iconAnimation = useAnimatedStyle(() => ({
      transform: [{ rotate: `${rotation.value}deg` }],
    }));

    const contentAnimation = useAnimatedStyle(() => ({ height: height.value }));

    const handleAccordionClick = useCallback(() => {
      if (disabled) return;

      if (isWrappedInAccordionGroup) {
        onAccordionGroupClick?.();
      } else {
        setIsExpanded((previouslyExpanded) => !previouslyExpanded);
      }
      onClick?.();
    }, [disabled, isWrappedInAccordionGroup, onAccordionGroupClick, onClick]);

    return (
      <Animated.View style={[staticStyles.animatedAccordionRoot, contentAnimation]}>
        <Container
          onLayout={(event) => {
            setRootContainerHeight(event.layout.height);
          }}
          ref={ref}
          styleConfig={{ root }}
        >
          <Container styleConfig={{ root: [staticStyles.labelRow, ...labelStyle] }} onClick={handleAccordionClick}>
            {label}
            {expandIcon && (
              <Animated.View
                style={[staticStyles.iconContainer, iconAnimation, ...(icon as AnimatedStyle<ViewStyle>[])]}
              >
                {expandIcon}
              </Animated.View>
            )}
          </Container>
          <Container
            onLayout={(event) => {
              setChildContainerHeight(event.layout?.height);
            }}
          >
            <Container styleConfig={{ root: [staticStyles.accordionContentRoot, ...childrenContainer] }}>
              {children}
            </Container>
          </Container>
        </Container>
      </Animated.View>
    );
  },
);

AccordionV2.displayName = 'AccordionV2';
export default AccordionV2;
