import { type MouseEvent, useState } from 'react';

import Tooltip from '@design-system/Tooltip';
import Typography from '@mui/material/Typography';
import { composeSx } from '@utils/components';
import { truncate } from 'lodash';

import { type TextOverflowTipProps } from './types';

/*
 * Differences with TypographyOverflowTooltip:
 * - TypographyOverflowTooltip detects horizontal overflow (scrollWidth > clientWidth) on mount and resize.
 *   Intended for single-line text with ellipsis.
 * - TextOverflowTip detects overflow on mouseEnter, covering three cases:
 *   1. `lineClamp`: vertical overflow (scrollHeight > clientHeight), for multiline text clipped with -webkit-line-clamp.
 *   2. `length`: character-based truncation via lodash truncate.
 *   3. No extra props: classic horizontal overflow, same behavior as TypographyOverflowTooltip.
 */

/**
 * Shows a tooltip with the full text when it is truncated.
 * Use `lineClamp` for multiline or `length` to truncate by character count.
 */
export const TextOverflowTip = ({
  primary,
  length,
  lineClamp,
  slotProps,
}: TextOverflowTipProps) => {
  const [tooltipEnabled, setTooltipEnabled] = useState(false);
  const shouldTruncate = length && length < primary.length && !lineClamp;

  const handleShouldShow = ({ currentTarget }: MouseEvent<Element>) => {
    if (shouldTruncate) {
      return setTooltipEnabled(true);
    }

    if (lineClamp && currentTarget.scrollHeight > currentTarget.clientHeight) {
      return setTooltipEnabled(true);
    }

    if (currentTarget.scrollWidth > currentTarget.clientWidth) {
      setTooltipEnabled(true);
    }
  };

  const { typography: typographyProps, tooltip: tooltipProps } =
    slotProps ?? {};

  return (
    <Tooltip
      title={primary}
      open={tooltipEnabled}
      direction="top"
      {...tooltipProps}
    >
      <Typography
        onMouseEnter={handleShouldShow}
        onMouseLeave={() => setTooltipEnabled(false)}
        noWrap={!shouldTruncate && !lineClamp}
        {...typographyProps}
        sx={composeSx(
          {
            ...(lineClamp && {
              WebkitLineClamp: lineClamp,
              WebkitBoxOrient: 'vertical',
              display: '-webkit-box',
              overflow: 'hidden',
              whiteSpace: 'normal',
              overflowWrap: 'break-word',
            }),
            ...(!lineClamp &&
              !length && {
                textOverflow: 'ellipsis',
                overflow: 'hidden',
                whiteSpace: 'nowrap',
              }),
            width: '100%',
            ...(!typographyProps?.variant && {
              fontSize: 'inherit',
              fontWeight: 'inherit',
            }),
          },
          typographyProps?.sx,
        )}
      >
        {shouldTruncate ? truncate(primary, { length }) : primary}
      </Typography>
    </Tooltip>
  );
};

export default TextOverflowTip;
