import {
  type ElementRef,
  useCallback,
  useLayoutEffect,
  useRef,
  useState,
} from 'react';

import { sumBy } from 'lodash-es';
import Box from '@material-hu/mui/Box';
import * as colors from '@material-hu/mui/colors';
import Stack from '@material-hu/mui/Stack';
import Tooltip from '@material-hu/mui/Tooltip';
import * as animations from '@material-hu/utils/animations';

type SerieItem = {
  id: string;
  value: number;
  color?: string;
};

export type LinearDistributionChartProps = {
  series: SerieItem[];
  getTooltipTitle?: (value: number, total: number, index: number) => string;
  variant?: 'large' | 'small';
};

const LinearDistributionChart = ({
  series,
  getTooltipTitle,
  variant = 'small',
}: LinearDistributionChartProps) => {
  const containerRef = useRef<ElementRef<typeof Stack>>(null);
  const seriesTotal = sumBy(series, item => item.value);
  const [containerWidth, setContainerWidth] = useState(0);
  const hasTooltip = !!getTooltipTitle;

  useLayoutEffect(() => {
    const updateContainerWidth = () => {
      if (containerRef.current) {
        const { width } = containerRef.current.getBoundingClientRect();
        setContainerWidth(width);
      }
    };

    updateContainerWidth();

    window.addEventListener('resize', updateContainerWidth);

    return () => {
      window.removeEventListener('resize', updateContainerWidth);
    };
  }, []);

  const renderSegment = useCallback(
    (item: SerieItem, index: number) => {
      const width = (containerWidth / seriesTotal) * item.value;

      if (!width) return null;

      const content = (
        <Box
          sx={{
            '@keyframes slideInUp': {
              '0%': {
                transform: 'translate3d(0, 100%, 0)',
                visibility: 'visible',
              },
              '100%': {
                transform: 'translate3d(0, 0, 0)',
              },
            },
            width,
            height: variant === 'large' ? 12 : 8,
            animation: `${animations.slideInUp} 250ms ease-in-out both`,
            animationDelay: `${index * 0.025}s`,
            borderRadius: variant === 'large' ? 1 : 4,
            backgroundColor: theme =>
              item.color ?? theme.palette.new.graphics.brand[500],
          }}
          {...(hasTooltip ? {} : { key: item.id })}
        />
      );

      return hasTooltip ? (
        <Tooltip
          key={item.id}
          title={getTooltipTitle(item.value, seriesTotal, index)}
          placement="top"
          slotProps={{
            tooltip: {
              sx: {
                backgroundColor: theme =>
                  theme.palette.new.background.layout.inverted,
                fontSize: theme => theme.typography.pxToRem(13),
                p: 1,
              },
            },
          }}
          followCursor
        >
          {content}
        </Tooltip>
      ) : (
        content
      );
    },
    [getTooltipTitle, hasTooltip, containerWidth],
  );

  return (
    <Stack
      ref={containerRef}
      sx={{
        alignItems: 'center',
        flexDirection: 'row',
        width: '100%',
        gap: 0.5,
      }}
    >
      {series.map(renderSegment)}
    </Stack>
  );
};

export default LinearDistributionChart;
