import Link from '@tiptap/extension-link';
import Placeholder from '@tiptap/extension-placeholder';
import { useEditor, EditorContent } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';

import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';

import { cn } from '@/lib/utils';

import { NlpHighlighterExtension } from './NlpHighlighterExtension';

interface TipTapEditorProps {
  value?: string;
  onChange?: (html: string) => void;
  placeholder?: string;
  className?: string;
  editable?: boolean;
  highlightTerms?: string[];
}

export interface TipTapEditorHandle {
  getHTML: () => string;
  setContent: (content: string) => void;
  focus: () => void;
  clear: () => void;
  getEditor: () => import('@tiptap/react').Editor | null;
}

const TipTapEditor = forwardRef<TipTapEditorHandle, TipTapEditorProps>(
  (
    {
      value = '',
      onChange,
      placeholder = 'Start typing...',
      className,
      editable = true,
      highlightTerms = [],
    },
    ref,
  ) => {
    // Ref so getTerms closure always reads the latest terms without stale capture
    const highlightTermsRef = useRef<string[]>(highlightTerms);

    const editor = useEditor({
      extensions: [
        StarterKit.configure({
          heading: {
            levels: [1, 2, 3, 4, 5, 6],
          },
          // Disable the built-in Link extension from StarterKit
          link: false,
        }),
        Link.configure({
          openOnClick: false,
          HTMLAttributes: {
            class: 'text-primary underline',
          },
        }),
        Placeholder.configure({
          placeholder,
        }),
        NlpHighlighterExtension.configure({
          getTerms: () => highlightTermsRef.current,
          getEnabled: () => highlightTermsRef.current.length > 0,
        }),
      ],
      content: value,
      editable,
      onUpdate: ({ editor }) => {
        const html = editor.getHTML();
        onChange?.(html);
      },
      editorProps: {
        attributes: {
          role: 'textbox',
          'aria-label': 'Content editor',
          'aria-multiline': 'true',
          class: cn(
            'prose prose-sm dark:prose-invert max-w-none',
            'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
            'min-h-[200px] px-3 py-2',
          ),
        },
      },
    });

    // Update editor content when value prop changes externally
    useEffect(() => {
      if (editor && value !== editor.getHTML()) {
        editor.commands.setContent(value);
      }
    }, [value, editor]);

    // Update editable state when prop changes
    useEffect(() => {
      if (editor) {
        editor.setEditable(editable);
      }
    }, [editable, editor]);

    // Sync highlight terms ref and trigger decoration rebuild
    useEffect(() => {
      highlightTermsRef.current = highlightTerms;
      if (editor && !editor.isDestroyed) {
        editor.view.dispatch(editor.view.state.tr.setMeta('updateHighlight', true));
      }
    }, [highlightTerms, editor]);

    // Expose methods via ref
    useImperativeHandle(ref, () => ({
      getHTML: () => editor?.getHTML() ?? '',
      setContent: (content: string) => {
        editor?.commands.setContent(content);
      },
      focus: () => {
        editor?.commands.focus();
      },
      clear: () => {
        editor?.commands.clearContent();
      },
      getEditor: () => editor,
    }));

    if (!editor) {
      return null;
    }

    return (
      <div
        className={cn(
          'rounded-md border border-input bg-background',
          'ring-offset-background',
          'focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2',
          className,
        )}
      >
        <EditorContent editor={editor} />
      </div>
    );
  },
);

TipTapEditor.displayName = 'TipTapEditor';

export default TipTapEditor;
