import { MouseEvent, useEffect, useRef, useState, useCallback } from 'react';
import { useTheme } from '@cleartrip/ct-design-theme';
import { Container } from '@cleartrip/ct-design-container';
import Conditional from '@cleartrip/ct-design-conditional-wrap';

import { ITooltipProps, TooltipStyles, TooltipArrowStyles } from './type';
import { overlayBorderRadius, positions } from './constants';
import { staticTooltipStyles } from './style';
import TooltipContainer from './TooltipContainer';
import TooltipArrow from './TooltipArrow';
import { Transition } from '@cleartrip/ct-design-transition';
import { TooltipChevronDown } from '@cleartrip/ct-design-icons';
import { useStyles, useWebMergeStyles } from '@cleartrip/ct-design-style-manager';
import { isEmpty } from '@cleartrip/ct-design-common-utils';
import { getTooltipStyles, getTooltipArrowStyles } from './webStyle';

const Tooltip: React.FC<ITooltipProps> = ({
  children,
  position = positions.RIGHT,
  labelContainer,
  tooltipWidth = 150,
  tooltipBorderRadius = overlayBorderRadius.MD,
  styleConfig,
  enableTooltipContainerHovering = false,
  open = false,
  animate = true,
  svgPathProps,
  anchorRef,
}) => {
  const theme = useTheme();
  const {
    root: customRootStyles = [],
    labelContainerStyles: customLabelContainerStyles = [],
    overlayStyles: customOverlayStyles = [],
    arrowStyles: customArrowStyles = [],
  } = styleConfig || {};
  const [styles, setStyles] = useState<{ tooltipStyles: TooltipStyles; tooltipArrowStyles: TooltipArrowStyles }>({
    tooltipStyles: {},
    tooltipArrowStyles: {},
  });
  const labelRef = useRef<HTMLDivElement>(null);
  const tooltipRef = useRef<HTMLDivElement>(null);

  const setTooltipStyles = useCallback(() => {
    const tooltipStyle = getTooltipStyles({
      borderSize: tooltipBorderRadius,
      position,
      labelRef,
      tooltipRef,
      anchorRef: anchorRef as React.RefObject<HTMLElement | null>,
      theme,
    });

    const tooltipArrowStyle = getTooltipArrowStyles({
      position,
      labelRef,
      tooltipRef,
      anchorRef: anchorRef as React.RefObject<HTMLElement | null>,
      theme,
    });
    setStyles({ tooltipStyles: tooltipStyle, tooltipArrowStyles: tooltipArrowStyle });
  }, [tooltipBorderRadius, position, labelRef, tooltipRef, anchorRef, theme]);

  useEffect(() => {
    if (open) {
      setTooltipStyles();
    } else {
      setStyles({ tooltipStyles: {}, tooltipArrowStyles: {} });
    }
  }, [open, setTooltipStyles]);

  const canCloseTooltipContainer = (event: MouseEvent<HTMLDivElement>) => {
    const defaultDimesstions = { right: 0, left: 0, bottom: 0, top: 0 };
    const tooltipDimesntions = tooltipRef.current?.getBoundingClientRect() ?? defaultDimesstions;
    const labelDimensions = labelRef.current?.getBoundingClientRect() ?? defaultDimesstions;

    const { r, l, b, t } = {
      r: Math.floor(Math.max(tooltipDimesntions.right, labelDimensions.left)),
      l: Math.floor(Math.min(tooltipDimesntions.left, labelDimensions.right)),
      b: Math.floor(Math.max(tooltipDimesntions.bottom, labelDimensions.top)),
      t: Math.floor(Math.min(tooltipDimesntions.top, labelDimensions.bottom)),
    };

    const currentX = event.clientX + 1;
    const currentY = event.clientY + 1;

    return r >= currentX && l <= currentX && t <= currentY && b >= currentY;
  };
  const handleMouseEnter = () => {
    setTooltipStyles();
  };

  const handleMouseLeave = (event: MouseEvent<HTMLDivElement>) => {
    if (enableTooltipContainerHovering && canCloseTooltipContainer(event)) return;
    setStyles({ tooltipStyles: {}, tooltipArrowStyles: {} });
  };

  const labelStyles = useWebMergeStyles([...customLabelContainerStyles], [customLabelContainerStyles]);

  const dynamicTooltipStyles = useStyles(() => {
    return {
      tooltip: styles.tooltipStyles,
      tooltipArrow: styles.tooltipArrowStyles,
    };
  }, [styles.tooltipStyles, open]);

  return (
    <Container styleConfig={{ root: [staticTooltipStyles?.root, ...customRootStyles] }}>
      <div onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} ref={labelRef} className={labelStyles}>
        {labelContainer}
      </div>
      {!!children && (
        <Conditional condition={animate} wrap={(child) => <Transition type='fade'>{child}</Transition>}>
          <>
            <TooltipContainer
              visible={!isEmpty(styles.tooltipStyles)}
              width={tooltipWidth}
              onMouseLeave={handleMouseLeave}
              styleConfig={{ root: [dynamicTooltipStyles.tooltip, ...customOverlayStyles] }}
              tooltipRef={tooltipRef}
            >
              {children}
            </TooltipContainer>
            <TooltipArrow
              visible={!isEmpty(styles.tooltipArrowStyles)}
              styleConfig={{ root: [dynamicTooltipStyles.tooltipArrow, ...customArrowStyles] }}
            >
              <TooltipChevronDown {...svgPathProps} />
            </TooltipArrow>
          </>
        </Conditional>
      )}
    </Container>
  );
};

export default Tooltip;
