import { EditorContent, ReactNodeViewRenderer, useEditor } from "@tiptap/react";
import { Placeholder } from "@tiptap/extension-placeholder";
import { StarterKit } from "@tiptap/starter-kit";
import { Mention, LinkExtension } from "@docmost/editor-ext";
import classes from "./comment.module.css";
import { useFocusWithin } from "@mantine/hooks";
import clsx from "clsx";
import { forwardRef, useEffect, useImperativeHandle } from "react";
import { useTranslation } from "react-i18next";
import EmojiCommand from "@/features/editor/extensions/emoji-command";
import mentionRenderItems from "@/features/editor/components/mention/mention-suggestion";
import MentionView from "@/features/editor/components/mention/mention-view";
import { platformModifierKey } from "@/lib";

interface CommentEditorProps {
  defaultContent?: any;
  onUpdate?: any;
  onSave?: any;
  editable: boolean;
  placeholder?: string;
  autofocus?: boolean;
  surface?: "default" | "muted";
}

const CommentEditor = forwardRef(
  (
    {
      defaultContent,
      onUpdate,
      onSave,
      editable,
      placeholder,
      autofocus,
      surface,
    }: CommentEditorProps,
    ref,
  ) => {
    const { t } = useTranslation();
    const { ref: focusRef, focused } = useFocusWithin();

    const commentEditor = useEditor({
      extensions: [
        StarterKit.configure({
          gapcursor: false,
          dropcursor: false,
          link: false,
        }),
        Placeholder.configure({
          placeholder: placeholder || t("Reply..."),
        }),
        LinkExtension,
        EmojiCommand,
        Mention.configure({
          suggestion: {
            allowSpaces: true,
            items: () => [],
            // @ts-ignore
            render: mentionRenderItems,
          },
          HTMLAttributes: {
            class: "mention",
          },
        }).extend({
          addNodeView() {
            this.editor.isInitialized = true;
            return ReactNodeViewRenderer(MentionView);
          },
        }),
      ],
      editorProps: {
        attributes: {
          "aria-label": placeholder || t("Comment"),
        },
        handleDOMEvents: {
          keydown: (_view, event) => {
            if (
              [
                "ArrowUp",
                "ArrowDown",
                "ArrowLeft",
                "ArrowRight",
                "Enter",
              ].includes(event.key)
            ) {
              const emojiCommand = document.querySelector("#emoji-command");
              const mentionPopup = document.querySelector("#mention");
              if (emojiCommand || mentionPopup) {
                return true;
              }
            }

            if (platformModifierKey(event) && event.code === "Enter") {
              event.preventDefault();
              if (onSave) onSave();

              return true;
            }
          },
        },
      },
      onUpdate({ editor }) {
        if (onUpdate) onUpdate(editor.getJSON());
      },
      content: defaultContent,
      editable,
      immediatelyRender: true,
      shouldRerenderOnTransaction: false,
      autofocus: (autofocus && "end") || false,
    });

    // Sync content from props for read-only editors (e.g. when updated via
    // websocket on another browser). Skip for editable editors to avoid
    // resetting the cursor position on every keystroke.
    useEffect(() => {
      if (!editable && commentEditor && !commentEditor.isDestroyed && defaultContent) {
        commentEditor.commands.setContent(defaultContent);
      }
    }, [defaultContent, editable, commentEditor]);

    useEffect(() => {
      setTimeout(() => {
        if (autofocus && commentEditor && !commentEditor.isDestroyed) {
          commentEditor.commands.focus("end");
        }
      }, 10);
    }, [commentEditor, autofocus]);

    useImperativeHandle(ref, () => ({
      clearContent: () => {
        if (commentEditor && !commentEditor.isDestroyed) {
          commentEditor.commands.clearContent();
        }
      },
    }));

    return (
      <div
        ref={focusRef}
        className={classes.commentEditor}
        data-editable={editable || undefined}
        data-surface={surface}
      >
        <EditorContent
          editor={commentEditor}
          className={clsx(classes.ProseMirror, { [classes.focused]: focused })}
        />
      </div>
    );
  },
);

export default CommentEditor;
