// Editor.jsx — the Discuss-mode read-only renderer (and main/no-contribute
// fallback). Tiptap on ProseMirror per §18; the Contribute-mode editing
// surface moved to MarkdownSourceEditor (CodeMirror 6) in the Phase 1
// rewrite of Contribute, leaving this surface for read-only rendering
// plus the §8.12 selection tooltip's coords.
//
// One ProseMirror plugin still lives alongside StarterKit:
//
//   • selectionHighlight — keeps a selected passage highlighted while
//     focus moves to the §8.12 selection tooltip. Driven by meta
//     transactions dispatched from the parent.
//
// The paragraph-margin gutter accent that used to live here is dropped;
// Phase 4 of the Contribute rewrite adds a proper change-anchored gutter
// against the CodeMirror raw pane.

import { useEditor, EditorContent, Extension } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import { useEffect, useRef, useCallback } from 'react'
import { renderMarkdown } from '../lib/sanitizeHtml'
import { Plugin, PluginKey } from 'prosemirror-state'
import { Decoration, DecorationSet } from 'prosemirror-view'

// ── Selection highlight plugin ────────────────────────────────────────────

export const selectionHighlightKey = new PluginKey('selectionHighlight')

function makeSelectionHighlightPlugin() {
  return new Plugin({
    key: selectionHighlightKey,
    state: {
      init: () => null,
      apply(tr, prev) {
        const meta = tr.getMeta(selectionHighlightKey)
        return meta !== undefined ? meta : prev
      },
    },
    props: {
      decorations(state) {
        const range = selectionHighlightKey.getState(state)
        if (!range || range.from >= range.to) return DecorationSet.empty
        try {
          return DecorationSet.create(state.doc, [
            Decoration.inline(range.from, range.to, { class: 'selection-highlight' }),
          ])
        } catch {
          return DecorationSet.empty
        }
      },
    },
  })
}

function SelectionHighlightExtension() {
  return Extension.create({
    name: 'selectionHighlight',
    addProseMirrorPlugins() {
      return [makeSelectionHighlightPlugin()]
    },
  })
}

// ── Editor component ──────────────────────────────────────────────────────

export default function Editor({
  content,
  editorRef,
  onSelectionChange,
  onUpdate,
  editable = true,
}) {
  const isMouseDownRef = useRef(false)

  const reportSelection = useCallback((editor) => {
    if (isMouseDownRef.current) return
    const { from, to } = editor.state.selection
    if (from !== to) {
      const text = editor.state.doc.textBetween(from, to, ' ')
      const coords = editor.view.coordsAtPos(from)
      onSelectionChange?.({ text, coords, from, to })
    } else {
      onSelectionChange?.(null)
    }
  }, [onSelectionChange])

  const editor = useEditor({
    extensions: [
      StarterKit,
      SelectionHighlightExtension(),
    ],
    content: '<p></p>',
    editable,
    onUpdate: ({ editor }) => {
      onUpdate?.(editor.getText(), editor.getHTML())
    },
    onSelectionUpdate: ({ editor }) => {
      reportSelection(editor)
    },
  })

  // Expose editor instance to the parent.
  useEffect(() => {
    if (editorRef) editorRef.current = editor
  }, [editor, editorRef])

  useEffect(() => {
    if (editor) editor.setEditable(editable)
  }, [editor, editable])

  useEffect(() => {
    if (!editor) return
    const el = editor.view.dom
    const onMouseDown = () => { isMouseDownRef.current = true; onSelectionChange?.(null) }
    const onMouseUp = () => { isMouseDownRef.current = false; reportSelection(editor) }
    el.addEventListener('mousedown', onMouseDown)
    document.addEventListener('mouseup', onMouseUp)
    return () => {
      el.removeEventListener('mousedown', onMouseDown)
      document.removeEventListener('mouseup', onMouseUp)
    }
  }, [editor, onSelectionChange, reportSelection])

  useEffect(() => {
    if (!editor || content == null) return
    const html = renderMarkdown(content)
    editor.commands.setContent(html, false)
  }, [content, editor])

  return (
    <div className="editor-wrapper">
      <EditorContent editor={editor} className="editor-content" />
    </div>
  )
}
