/**
 * Blog Editor Component
 * Extends the base RichTextEditor with blog-specific functionality
 */

import { LexicalComposer } from '@lexical/react/LexicalComposer'
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'
import { ContentEditable } from '@lexical/react/LexicalContentEditable'
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin'
import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary'
import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin'
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
import { HeadingNode, QuoteNode } from '@lexical/rich-text'
import { CodeNode, CodeHighlightNode } from '@lexical/code'
import { ListItemNode, ListNode } from '@lexical/list'
import { ListPlugin } from '@lexical/react/LexicalListPlugin'
import { CheckListPlugin } from '@lexical/react/LexicalCheckListPlugin'
import { HorizontalRuleNode } from '@lexical/react/LexicalHorizontalRuleNode'
import { TableCellNode, TableNode, TableRowNode } from '@lexical/table'
import { TablePlugin } from '@lexical/react/LexicalTablePlugin'
import { LinkNode, AutoLinkNode } from '@lexical/link'
import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin'
import { AutoLinkPlugin } from '@lexical/react/LexicalAutoLinkPlugin'
import { HashtagNode } from '@lexical/hashtag'
import { $generateHtmlFromNodes } from '@lexical/html'
import type { EditorState } from 'lexical'

import { ImageNode } from '../../editor/nodes/ImageNode'
import { MentionNode } from '../../editor/nodes/MentionNode'
import ToolbarPlugin from '../../editor/plugins/ToolbarPlugin'
import MarkdownPlugin from '../../editor/plugins/MarkdownShortcutPlugin'
import HashtagPlugin from '../../editor/plugins/HashtagPlugin'
import MentionsPlugin from '../../editor/plugins/MentionsPlugin'
import editorTheme from '../../editor/themes/EditorTheme'
import { BlogImagePlugin } from './BlogImagePlugin'
import '../../editor/styles/editor.css'

const URL_MATCHER =
  /((https?:\/\/(www\.)?)|(www\.))[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/

const EMAIL_MATCHER =
  /(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/

const MATCHERS = [
  (text: string) => {
    const match = URL_MATCHER.exec(text)
    if (match === null) {
      return null
    }
    const fullMatch = match[0]
    return {
      index: match.index,
      length: fullMatch.length,
      text: fullMatch,
      url: fullMatch.startsWith('http') ? fullMatch : `https://${fullMatch}`,
    }
  },
  (text: string) => {
    const match = EMAIL_MATCHER.exec(text)
    if (match === null) {
      return null
    }
    const fullMatch = match[0]
    return {
      index: match.index,
      length: fullMatch.length,
      text: fullMatch,
      url: `mailto:${fullMatch}`,
    }
  },
]

interface BlogEditorProps {
  placeholder?: string
  onChange?: (html: string) => void
}

/**
 * OnChange wrapper component that has access to editor context
 */
function OnChangeWrapper({ onChange }: { onChange?: (html: string) => void }) {
  const [editor] = useLexicalComposerContext()

  const handleChange = (editorState: EditorState) => {
    editorState.read(() => {
      const html = $generateHtmlFromNodes(editor)
      onChange?.(html)
    })
  }

  return <OnChangePlugin onChange={handleChange} />
}

export default function BlogEditor({ placeholder, onChange }: BlogEditorProps) {
  const editorConfig = {
    namespace: 'BlogEditor',
    theme: editorTheme,
    onError(error: Error) {
      console.error(error)
    },
    nodes: [
      HeadingNode,
      QuoteNode,
      CodeNode,
      CodeHighlightNode,
      ListNode,
      ListItemNode,
      HorizontalRuleNode,
      TableNode,
      TableRowNode,
      TableCellNode,
      LinkNode,
      AutoLinkNode,
      ImageNode,
      HashtagNode,
      MentionNode,
    ],
  }

  return (
    <LexicalComposer initialConfig={editorConfig}>
      <div className="editor-container">
        <ToolbarPlugin />
        <div className="editor-inner">
          <RichTextPlugin
            contentEditable={<ContentEditable className="editor-input" />}
            placeholder={
              <div className="editor-placeholder">
                {placeholder || 'Start writing your blog post...'}
              </div>
            }
            ErrorBoundary={LexicalErrorBoundary}
          />
          <OnChangeWrapper onChange={onChange} />
          <HistoryPlugin />
          <ListPlugin />
          <CheckListPlugin />
          <LinkPlugin />
          <AutoLinkPlugin matchers={MATCHERS} />
          <TablePlugin />
          <BlogImagePlugin />
          <HashtagPlugin />
          <MentionsPlugin />
          <MarkdownPlugin />
        </div>
      </div>
    </LexicalComposer>
  )
}
