import { FC, useLayoutEffect, useRef, useState } from 'react';

import Chip from '@material-hu/mui/Chip';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import HuTooltip from '@material-hu/components/design-system/Tooltip';

import { ArticleTopics } from 'src/types/news';
import { useLokaliseTranslation as useTranslation } from 'src/utils/i18n';

type TopicChipsProps = {
  topics: ArticleTopics[];
};

const CHIP_GAP = 8; // MUI spacing 1 = 8px
const OVERFLOW_CHIP_WIDTH = 40; // approximate width of "+N" chip

const chipSx = {
  color: (theme: any) => theme.palette.new.text.neutral.lighter,
  '& .MuiChip-label': {
    px: 1,
    fontWeight: 600,
  },
};

const TopicChips: FC<TopicChipsProps> = ({ topics }) => {
  const { t } = useTranslation(['news']);
  const containerRef = useRef<HTMLDivElement>(null);
  const chipWidthsRef = useRef<number[]>([]);
  const prevTopicsRef = useRef(topics);
  const [visibleCount, setVisibleCount] = useState<number | null>(null);

  // Reset when topics identity changes
  if (prevTopicsRef.current !== topics) {
    prevTopicsRef.current = topics;
    chipWidthsRef.current = [];
    setVisibleCount(null);
  }

  const isMeasuring = visibleCount === null;

  useLayoutEffect(() => {
    const container = containerRef.current;
    if (!container || !topics.length) return;

    if (isMeasuring) {
      const chips = Array.from(
        container.querySelectorAll('[data-chip]'),
      ) as HTMLElement[];
      chipWidthsRef.current = chips.map(c => c.offsetWidth);
    }

    const calculate = () => {
      const containerWidth = container.offsetWidth;
      const widths = chipWidthsRef.current;
      if (!widths.length) return;

      let used = 0;
      let fits = 0;

      for (let i = 0; i < widths.length; i++) {
        const w = widths[i] + (fits > 0 ? CHIP_GAP : 0);
        if (used + w > containerWidth) break;
        used += w;
        fits++;
      }

      if (fits < topics.length) {
        used = 0;
        fits = 0;
        for (let i = 0; i < widths.length; i++) {
          const w = widths[i] + (fits > 0 ? CHIP_GAP : 0);
          if (used + w + CHIP_GAP + OVERFLOW_CHIP_WIDTH > containerWidth) break;
          used += w;
          fits++;
        }
        fits = Math.max(fits, 1);
      }

      setVisibleCount(fits);
    };

    calculate();

    const observer = new ResizeObserver(calculate);
    observer.observe(container);
    return () => observer.disconnect();
  }, [topics, isMeasuring]);

  if (!topics.length) return null;

  const overflowCount =
    visibleCount !== null ? topics.length - visibleCount : 0;
  const hiddenTopics = visibleCount !== null ? topics.slice(visibleCount) : [];

  return (
    <Stack
      ref={containerRef}
      flexDirection="row"
      sx={{
        flexWrap: 'nowrap',
        gap: 1,
        px: 2,
        overflow: 'hidden',
        visibility: isMeasuring ? 'hidden' : 'visible',
      }}
    >
      {(isMeasuring ? topics : topics.slice(0, visibleCount)).map(topic => (
        <Chip
          key={topic.id}
          data-chip
          label={topic.name}
          variant="outlined"
          size="small"
          sx={chipSx}
        />
      ))}
      {overflowCount > 0 && (
        <HuTooltip
          title={
            <Stack sx={{ gap: 0.5 }}>
              <Typography
                variant="globalS"
                fontWeight="fontWeightBold"
                color="common.white"
              >
                {t('news:topics')}
              </Typography>
              {hiddenTopics.map(topic => (
                <Typography
                  key={topic.id}
                  variant="globalXS"
                  color="common.white"
                >
                  {topic.name}
                </Typography>
              ))}
            </Stack>
          }
        >
          <Chip
            label={`+${overflowCount}`}
            variant="outlined"
            size="small"
            sx={chipSx}
          />
        </HuTooltip>
      )}
    </Stack>
  );
};

export default TopicChips;
