import { MouseEvent, useState } from 'react';
import { useFormContext } from 'react-hook-form';

import { Editor } from 'tinymce';

import Add from '@material-hu/icons/material/Add';
import Close from '@material-hu/icons/material/Close';
import FormHelperText from '@material-hu/mui/FormHelperText';
import Stack, { StackProps } from '@material-hu/mui/Stack';
import { useTheme } from '@material-hu/mui/styles';
import Typography from '@material-hu/mui/Typography';

import Button, {
  ButtonProps,
} from '@material-hu/components/design-system/Buttons/Button';

import { useLokaliseTranslation } from 'src/utils/i18n';

import {
  FormRichEditor,
  FormRichEditorProps,
} from 'src/components/FormInputs/FormRichEditor';

/**
 * Truncates HTML content to a max character length while preserving HTML structure.
 * This keeps line breaks (<p>, <br>) intact instead of collapsing them.
 */
export const getTruncatedHtml = (editor: Editor, maxLength: number): string => {
  const htmlContent = editor.getContent({ format: 'html' });
  const container = document.createElement('div');
  container.innerHTML = htmlContent;

  const textLength = container.textContent?.length || 0;
  if (!maxLength || textLength <= maxLength) return htmlContent;

  let currentLength = 0;

  const truncate = (node: Node): boolean => {
    // Handle text nodes: truncate if we exceed the limit
    if (node.nodeType === Node.TEXT_NODE) {
      const text = node.textContent || '';
      const charsLeft = maxLength - currentLength;

      if (text.length > charsLeft) {
        node.textContent = text.substring(0, charsLeft);
        return true;
      }

      currentLength += text.length;
      return false;
    }

    // Handle element nodes: process children and remove extras after truncation
    if (node.nodeType === Node.ELEMENT_NODE) {
      const children = Array.from(node.childNodes);
      const cutIndex = children.findIndex(child => truncate(child));

      if (cutIndex !== -1) {
        children.slice(cutIndex + 1).forEach(child => child.remove());
        return true;
      }
    }

    return false;
  };

  truncate(container);
  return container.innerHTML;
};

export type FormAddDescriptionProps = FormRichEditorProps & {
  openLabel: string;
  closeLabel: string;
  onOpen?: (event: MouseEvent<HTMLButtonElement>) => void;
  onClose?: (event: MouseEvent<HTMLButtonElement>) => void;
  containerProps?: StackProps;
  buttonProps?: ButtonProps;
  disabled?: boolean;
  maxLength?: number;
  showCounter?: boolean;
  helperText?: string;
};

export const FormAddDescription = ({
  name,
  rules,
  openLabel,
  closeLabel,
  placeholder = '',
  onOpen = () => null,
  onClose = () => null,
  containerProps = {},
  buttonProps = {},
  disabled = false,
  maxLength,
  showCounter = false,
  helperText: helperTextProp = '',
  ...inputProps
}: FormAddDescriptionProps) => {
  const theme = useTheme();
  const { t } = useLokaliseTranslation('backoffice_only');
  const { watch, setValue } = useFormContext();

  const htmlContentValue = watch(name);

  const [open, setOpen] = useState(!!htmlContentValue);
  const [textContent, setTextContent] = useState('');

  const handleOpen = (event: MouseEvent<HTMLButtonElement>) => {
    setOpen(true);
    onOpen(event);
  };

  const handleClose = (event: MouseEvent<HTMLButtonElement>) => {
    setOpen(false);
    setValue(name, '');
    onClose(event);
  };

  const getHelperText = () => {
    if (showCounter) {
      return t('backoffice_only:form_text_field.characters_counter', {
        count: textContent.length,
        max: maxLength,
      });
    }
    return helperTextProp;
  };

  const helperText = getHelperText();

  const handleEditorChange = (newValue: string, editor: Editor) => {
    const newContent = editor.getContent({ format: 'text' });

    let formattedText = newContent;
    let formattedHtml = newValue;

    if (maxLength && newContent.length > maxLength) {
      formattedText = newContent.substring(0, maxLength);
      formattedHtml = getTruncatedHtml(editor, maxLength);
    }

    setTextContent(formattedText);
    return formattedHtml;
  };

  const handleEditorInit = (_: any, editor: Editor) => {
    const newContent = editor.getContent({ format: 'text' });
    setTextContent(newContent);
  };

  return (
    <Stack
      sx={{
        gap: 1,
        px: 3,
        justifyContent: 'center',
        alignItems: 'center',
        '& > *': {
          width: '100%',
        },
        ...containerProps.sx,
      }}
      {...containerProps}
    >
      <Stack
        sx={{
          flexDirection: 'row',
          justifyContent: 'flex-start',
          alignItems: 'center',
        }}
      >
        <Button
          id="form-add-description-button"
          variant="text"
          onClick={!open ? handleOpen : handleClose}
          disabled={disabled}
          startIcon={
            !open ? <Add fontSize="small" /> : <Close fontSize="small" />
          }
          sx={{
            color: theme.palette.text.primary,
            ...buttonProps.sx,
          }}
          {...buttonProps}
        >
          <Typography variant="subtitle2">
            {!open ? openLabel : closeLabel}
          </Typography>
        </Button>
      </Stack>
      {open && (
        <>
          <FormRichEditor
            simplifyEditor
            disabled={disabled}
            {...inputProps}
            name={name}
            placeholder={placeholder}
            aria-describedby={helperText ? `${name}-helper-text` : undefined}
            onEditorChange={handleEditorChange}
            onInit={handleEditorInit}
            editorProps={{
              id: name,
              value: htmlContentValue,
              ...inputProps?.editorProps,
            }}
          />
          {helperText && (
            <FormHelperText id={`${name}-helper-text`}>
              {helperText}
            </FormHelperText>
          )}
        </>
      )}
    </Stack>
  );
};

export default FormAddDescription;
