'use client'

import React, { useRef, useEffect } from 'react'

import { useEditor, EditorContent, type Editor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import Underline from '@tiptap/extension-underline'
import TextAlign from '@tiptap/extension-text-align'
import TextStyle from '@tiptap/extension-text-style'
import Subscript from '@tiptap/extension-subscript'
import Superscript from '@tiptap/extension-superscript'
import Placeholder from '@tiptap/extension-placeholder'
import Highlight from '@tiptap/extension-highlight'
import TaskList from '@tiptap/extension-task-list'
import TaskItem from '@tiptap/extension-task-item'
import BulletList from '@tiptap/extension-bullet-list'
import ListItem from '@tiptap/extension-list-item'
import OrderedList from '@tiptap/extension-ordered-list'
import Blockquote from '@tiptap/extension-blockquote'
import Table from '@tiptap/extension-table'
import TableRow from '@tiptap/extension-table-row'
import TableCell from '@tiptap/extension-table-cell'
import TableHeader from '@tiptap/extension-table-header'
import { toast } from 'sonner'

import { FontSize } from './extensions/font-size'
import ImageResize from 'tiptap-extension-resize-image'
import { Toolbar } from './Toolbar'

interface RichTextEditorProps {
  value: string
  onChange: (val: string) => void
  disabled?: boolean
  height?: string
  className?: string
  placeholder?: string
  debounceMs?: number
  onReady?: (editor: Editor) => void
  onFocus?: () => void
  onBlur?: () => void
}

export default function RichTextEditor({
  value,
  onChange,
  disabled,
  height = '300px',
  className,
  placeholder,
  debounceMs = 200,
  onReady,
  onFocus,
  onBlur,
}: RichTextEditorProps) {
  const updateTimerRef = useRef<number | undefined>(undefined)

  const computedExtensions: unknown[] = [
    StarterKit.configure({
      bulletList: false,
      orderedList: false,
      listItem: false,
      blockquote: false,
      codeBlock: false,
      code: false,
      heading: { levels: [1, 2, 3] },
      horizontalRule: false,
    }),
    Underline,
    ImageResize,
    TextAlign.configure({
      types: ['heading', 'paragraph'],
      alignments: ['left', 'center', 'right', 'justify'],
      defaultAlignment: 'left',
    }),
    Subscript,
    Superscript,
    TextStyle,
    FontSize,
    Table.configure({ resizable: true }),
    TableRow,
    TableCell,
    TableHeader,
    Highlight.configure({ multicolor: true }),
    TaskList,
    TaskItem.configure({ nested: true }),
    BulletList.configure({
      HTMLAttributes: {
        class: 'list-disc ml-5',
      },
    }),
    ListItem.configure({
      HTMLAttributes: {
        class: 'list-item my-0.5',
      },
    }),
    OrderedList.configure({
      HTMLAttributes: {
        class: 'list-decimal ml-5',
      },
    }),
    Blockquote.configure({
      HTMLAttributes: {
        class: 'border-l-4 pl-4 my-3 italic',
      },
    }),
  ]

  if (placeholder) {
    computedExtensions.push(Placeholder.configure({ placeholder }))
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const extensionsForEditor = computedExtensions as any

  const editor = useEditor({
    extensions: extensionsForEditor,
    content: value,
    editable: !disabled,
    enablePasteRules: false,
    enableInputRules: false,
    immediatelyRender: false,
    editorProps: {
      attributes: {
        class:
          'w-full h-full min-h-full bg-background px-3 py-2 text-sm leading-[1.6] ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 prose prose-sm max-w-none',
      },
      handleDrop: (view, event, slice, moved) => {
        if (!moved && event.dataTransfer?.files.length) {
          const file = event.dataTransfer.files[0]
          if (file.type.startsWith('image/')) {
            handleImageUpload(file)
            return true
          }
        }
        return false
      },
      handlePaste: (view, event) => {
        if (event.clipboardData?.files.length) {
          const file = event.clipboardData.files[0]
          if (file.type.startsWith('image/')) {
            handleImageUpload(file)
            return true
          }
        }
        return false
      },
      handleDOMEvents: {
        focus: () => {
          onFocus?.()
          return false
        },
        blur: () => {
          onBlur?.()
          return false
        },
      },
    },
    onUpdate: ({ editor }) => {
      if (updateTimerRef.current) window.clearTimeout(updateTimerRef.current)
      updateTimerRef.current = window.setTimeout(() => {
        onChange(editor.getHTML())
      }, debounceMs) as unknown as number
    },
  })

  useEffect(() => {
    if (!editor) return
    const current = editor.getHTML()
    if (value !== current) {
      editor.commands.setContent(value, false)
    }
  }, [editor, value])

  useEffect(() => {
    if (!editor) return
    editor.setEditable(!disabled)
  }, [editor, disabled])

  const readyCalledRef = useRef(false)
  useEffect(() => {
    if (!editor || readyCalledRef.current) return
    readyCalledRef.current = true
    onReady?.(editor)
  }, [editor, onReady])

  const readFileAsDataURL = (file: File): Promise<string> =>
    new Promise((resolve, reject) => {
      const reader = new FileReader()
      reader.onload = e => resolve(String(e.target?.result))
      reader.onerror = reject
      reader.readAsDataURL(file)
    })

  const handleImageUpload = async (file: File) => {
    if (file.size > 3 * 1024 * 1024) {
      toast.error('이미지 크기는 3 MB 이하만 지원됩니다.')
      return
    }
    if (!file.type.startsWith('image/')) {
      toast.error('이미지 파일만 업로드 가능합니다.')
      return
    }
    try {
      const dataUrl = await readFileAsDataURL(file)
      editor?.chain().focus().setImage({ src: dataUrl, alt: file.name }).run()
    } catch (error) {
      console.error(error)
      toast.error('이미지 읽기에 실패했습니다.')
    }
  }

  const containerStyle = { height }

  return (
    <div className={`border rounded-md bg-background flex flex-col ${className ?? ''}`} style={containerStyle}>
      <div className="flex-none border-b">
        <Toolbar editor={editor} disabled={disabled} onSelectImageFile={handleImageUpload} />
      </div>
      <div className="flex-1 min-h-0 overflow-y-auto">
        <EditorContent editor={editor} className="h-full" />
      </div>
    </div>
  )
}


