import { useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';

import { HTMLBody } from '@composed-components/HTMLBody';
import { Button, Stack, Typography } from '@mui/material';
import { isTextClamped, mapNewLines } from '@utils/string';

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

export const SeeMoreText = ({
  seeMoreText,
  seeLessText,
  lines = 3,
  isHtmlText = false,
  text,
  buttonSx,
  typographyProps,
}: SeeMoreTextProps) => {
  const [show, setShow] = useState(false);
  const [isCroped, setIsCroped] = useState(false);

  const textRef = useRef(null);

  const { t } = useTranslation('material_hu_only');

  const handleSeeMore = () => setShow(true);
  const handleSeeLess = () => setShow(false);

  const formatedText = useMemo(() => mapNewLines(text), [text]);

  useEffect(() => {
    if (textRef.current) {
      setIsCroped(isTextClamped(textRef));
    }
  }, [show, text]);

  if (lines < 1) {
    return <Typography {...typographyProps}>{formatedText}</Typography>;
  }

  const renderText = () => {
    const clippedSx = !show
      ? ({
          width: '100%',
          display: '-webkit-box',
          overflow: 'hidden',
          WebkitBoxOrient: 'vertical',
          WebkitLineClamp: `${lines}`,
          WebkitBoxFlex: '1',
        } as const)
      : {};

    if (isHtmlText) {
      return (
        <Typography
          ref={textRef}
          {...typographyProps}
          sx={{ ...clippedSx, ...typographyProps?.sx }}
        >
          <HTMLBody body={text} />
        </Typography>
      );
    }

    return (
      <Typography
        ref={textRef}
        {...typographyProps}
        sx={{ ...clippedSx, ...typographyProps?.sx }}
      >
        {formatedText}
      </Typography>
    );
  };

  return (
    <Stack
      sx={{
        '.MuiButton-root': {
          p: 0,
          minWidth: 0,
        },
        alignItems: 'flex-start',
        gap: 1,
      }}
    >
      {renderText()}
      {show && (
        <Button
          sx={buttonSx}
          onClick={handleSeeLess}
        >
          {seeLessText || t('see_more_text.see_less')}
        </Button>
      )}
      {!show && isCroped && (
        <Button
          sx={buttonSx}
          onClick={handleSeeMore}
        >
          {seeMoreText || t('see_more_text.see_more')}
        </Button>
      )}
    </Stack>
  );
};

export default SeeMoreText;
