"use client";

import { useEditor, EditorContent } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import Link from "@tiptap/extension-link";
import Underline from "@tiptap/extension-underline";
import Highlight from "@tiptap/extension-highlight";
import Placeholder from "@tiptap/extension-placeholder";
import TextAlign from "@tiptap/extension-text-align";
import { TextStyle } from "@tiptap/extension-text-style";
import { FontSize } from "@tiptap/extension-text-style/font-size";
import Color from "@tiptap/extension-color";

import TaskList from "@tiptap/extension-task-list";
import TaskItem from "@tiptap/extension-task-item";
import CharacterCountExtension from "@tiptap/extension-character-count";
import HorizontalRule from "@tiptap/extension-horizontal-rule";

import Subscript from "@tiptap/extension-subscript";
import Superscript from "@tiptap/extension-superscript";
import { useEffect } from "react";

import Toolbar from "./Toolbar";
import CharacterCount from "./CharacterCount";
import { type TextEditorProps } from "./types";
import "./editor.css";

/**
 * Full-featured Tiptap rich text editor with a responsive toolbar.
 *
 * Usage:
 * ```tsx
 * <TextEditor
 *   content="<p>Hello world</p>"
 *   onChange={(html) => console.log(html)}
 *   placeholder="Start writing..."
 *   characterLimit={500000}
 *   maxHeight="400px"
 * />
 * ```
 */
export default function TextEditor({
  content = "",
  onChange,
  placeholder = "Start writing...",
  editable = true,
  showCharacterCount = true,
  characterLimit = 0,
  className = "",
  minHeight = "200px",
  maxHeight = "500px",
  onEditorReady,
}: TextEditorProps) {
  const editor = useEditor({
    immediatelyRender: false,
    extensions: [
      StarterKit.configure({
        // We add our own configured HorizontalRule / CodeBlock below,
        // so disable the StarterKit defaults to avoid duplicate extensions.
        horizontalRule: false,
        codeBlock: false,
      }),
      Underline,
      Link.configure({
        openOnClick: false,
        autolink: true,
        HTMLAttributes: {
          rel: "noopener noreferrer",
          target: "_blank",
        },
      }),
      Highlight.configure({ multicolor: true }),
      Placeholder.configure({ placeholder }),
      TextAlign.configure({
        types: ["heading", "paragraph"],
      }),
      TextStyle,
      Color,
      FontSize,
      TaskList,
      TaskItem.configure({ nested: true }),
      CharacterCountExtension.configure({
        limit: characterLimit > 0 ? characterLimit : undefined,
      }),
      HorizontalRule,
      Subscript,
      Superscript,
    ],
    content,
    editable,
    onUpdate: ({ editor }) => {
      onChange?.(editor.getHTML());
    },
  });

  useEffect(() => {
    if (editor && onEditorReady) {
      onEditorReady(editor);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [editor]);

  // Keep editor content in sync if the `content` prop changes from outside
  // (e.g. loading a different document), without fighting the user's typing.
  useEffect(() => {
    if (editor && content !== undefined && content !== editor.getHTML()) {
      editor.commands.setContent(content, { emitUpdate: false });
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [content, editor]);

  if (!editor) {
    return (
      <div
        className={`
          flex items-center justify-center rounded-lg border border-zinc-200
          bg-white text-sm text-zinc-400 
          ${className}
        `}
        style={{ minHeight }}
      >
        Loading editor...
      </div>
    );
  }

  return (
    <div
      className={`
        tiptap-editor flex w-full flex-col overflow-hidden rounded-lg border
        border-zinc-200 bg-white shadow-sm
        
        ${className}
      `}
      style={{ "--editor-min-height": minHeight } as React.CSSProperties}
    >
      {editable && <Toolbar editor={editor} />}

      <div className="flex-1 overflow-y-auto" style={{ maxHeight }}>
        <EditorContent editor={editor} />
      </div>

      {showCharacterCount && (
        <CharacterCount editor={editor} limit={characterLimit} />
      )}
    </div>
  );
}
