import React, { useEffect } from 'react';
import classNames from 'clsx';
import { TextStyle } from '@tiptap/extension-text-style';
import { EditorContent, useEditor } from '@tiptap/react';
import { StarterKit } from '@tiptap/starter-kit';

import { getCharacterCount } from '@/modules/forms/helpers';

import MenuBar from './components/MenuBar/MenuBar';
import { Box, FormHelperText, FormLabel, Stack, Typography } from '@/mui/components';

import styles from './RichEditor.module.scss';

const TextStyleWithFontSize = TextStyle.extend({
  addAttributes() {
    return {
      ...(this.parent?.() ?? {}),
      fontSize: {
        default: null,
        parseHTML: (element: HTMLElement) => (element as HTMLElement).style.fontSize || '',
        renderHTML: (attrs) => (!attrs.fontSize ? {} : { style: `font-size: ${attrs.fontSize}` }),
      },
      fontFamily: {
        default: null,
        parseHTML: (element: HTMLElement) => (element as HTMLElement).style.fontFamily || '',
        renderHTML: (attrs) => (!attrs.fontFamily ? {} : { style: `font-family: ${attrs.fontFamily}` }),
      },
      color: {
        default: null,
        parseHTML: (element: HTMLElement) => (element as HTMLElement).style.color || '',
        renderHTML: (attrs) => (!attrs.color ? {} : { style: `color: ${attrs.color}` }),
      },
    };
  },
});

export type RichEditorProps = {
  disabled?: boolean;
  error?: boolean;
  helperText?: string;
  label?: string;
  maxLength: number;
  name?: string;
  placeholder?: string;
  readOnly?: boolean;
  required?: boolean;
  type: 'title' | 'description';
  value?: string;
  onChange?: (html: string) => void;
  onFocus?: () => void;
};

function RichEditor({
  value,
  name,
  onChange,
  onFocus,
  label,
  required,
  type,
  helperText,
  error,
  disabled,
  maxLength,
  readOnly,
  // placeholder = 'Paste content here...',
}: RichEditorProps) {
  const editor = useEditor({
    immediatelyRender: false,
    editable: !readOnly,
    extensions: [
      StarterKit.configure({
        bulletList: {
          keepMarks: true,
          keepAttributes: true,
        },
        orderedList: {
          keepMarks: true,
          keepAttributes: true,
        },
        link: {
          openOnClick: false,
          autolink: true,
          linkOnPaste: true,
          defaultProtocol: 'https',
          protocols: ['https', 'http', 'mailto', 'tel'],
          HTMLAttributes: { rel: 'noopener noreferrer nofollow', target: '_blank' },
        },
      }),
      TextStyleWithFontSize,
    ],
    content: value,
    onUpdate: (props$) => onChange?.(props$.editor.getHTML()),
  });

  useEffect(() => {
    if (editor && typeof value === 'string') {
      const current = editor.getHTML();

      if (current !== value) {
        editor.commands.setContent(value, {});
      }
    }
  }, [editor, value]);

  if (!editor) return null;

  return (
    <Stack direction="column" fullWidth spacing={1}>
      <Box
        className={classNames(styles.Wrapper, {
          [styles.Wrapper___error]: error,
        })}
      >
        <input type="text" name={name} value={value} className={styles.FormAnchor} />
        {label && (
          <FormLabel className={classNames(styles.Label)} disabled={disabled} error={error} required={required}>
            {label}
          </FormLabel>
        )}
        <MenuBar editor={editor} disabled={disabled} type={type} />
        <EditorContent editor={editor} disabled={disabled} className={styles.Editor} onFocus={onFocus} />
      </Box>
      <Stack spacing={1} fullWidth direction="row" justifyContent="space-between">
        <FormHelperText error={error} disabled={disabled}>
          {helperText}
        </FormHelperText>
        <Typography
          variant="caption"
          color="text.primary"
          component={Stack}
          direction="row"
          alignItems="center"
          spacing={1}
          className={styles.MaxLength}
        >
          <span>{getCharacterCount(value || '')}</span>
          <span>/</span>
          <span>{maxLength}</span>
        </Typography>
      </Stack>
    </Stack>
  );
}

export default RichEditor;
