import { useCallback, useEffect, useRef } from 'react'
import {
  Bold,
  IndentDecrease,
  IndentIncrease,
  Italic,
  List,
  ListOrdered,
  Underline,
} from 'lucide-react'
import styles from './RichTextEditor.module.css'

const INDENT_STEP_PX = 24
const INDENT_BLOCK_TAGS = new Set(['P', 'DIV', 'LI', 'BLOCKQUOTE', 'H1', 'H2', 'H3', 'H4'])

interface RichTextEditorProps {
  value: string
  onChange: (value: string) => void
  placeholder?: string
  /** Compact editor height for short fields like invoice top text. */
  editorMinHeight?: number
}

export function RichTextEditor({
  value,
  onChange,
  placeholder = '',
  editorMinHeight = 88,
}: RichTextEditorProps) {
  const editorRef = useRef<HTMLDivElement>(null)

  const syncChange = useCallback(() => {
    if (editorRef.current) {
      onChange(editorRef.current.innerHTML)
    }
  }, [onChange])

  useEffect(() => {
    if (editorRef.current && editorRef.current.innerHTML !== value) {
      editorRef.current.innerHTML = value
    }
  }, [value])

  function exec(command: string) {
    editorRef.current?.focus()
    document.execCommand(command)
    syncChange()
  }

  function findIndentBlock(editor: HTMLElement): HTMLElement | null {
    const selection = window.getSelection()
    if (!selection || selection.rangeCount === 0) return null

    let node: Node | null = selection.anchorNode
    while (node && node !== editor) {
      if (node instanceof HTMLElement && INDENT_BLOCK_TAGS.has(node.tagName)) {
        return node
      }
      node = node.parentNode
    }
    return null
  }

  function changeIndent(direction: 1 | -1) {
    const editor = editorRef.current
    if (!editor) return

    editor.focus()
    const block = findIndentBlock(editor)
    if (!block) {
      document.execCommand(direction > 0 ? 'indent' : 'outdent')
      syncChange()
      return
    }

    const current =
      Number.parseFloat(block.style.paddingInlineStart) ||
      Number.parseFloat(getComputedStyle(block).paddingInlineStart) ||
      0
    const next = Math.max(0, Math.round(current + direction * INDENT_STEP_PX))
    if (next === 0) {
      block.style.paddingInlineStart = ''
    } else {
      block.style.paddingInlineStart = `${next}px`
    }
    syncChange()
  }

  function onEditorKeyDown(e: React.KeyboardEvent<HTMLDivElement>) {
    if (e.key !== 'Tab' || e.altKey || e.ctrlKey || e.metaKey) return
    e.preventDefault()
    changeIndent(e.shiftKey ? -1 : 1)
  }

  return (
    <div className={styles.wrapper}>
      <div className={styles.toolbar}>
        <button type="button" onClick={() => exec('bold')} title="Bold" aria-label="Bold">
          <Bold size={14} />
        </button>
        <button type="button" onClick={() => exec('italic')} title="Italic" aria-label="Italic">
          <Italic size={14} />
        </button>
        <button
          type="button"
          onClick={() => exec('underline')}
          title="Underline"
          aria-label="Underline"
        >
          <Underline size={14} />
        </button>
        <span className={styles.divider} />
        <button
          type="button"
          onClick={() => exec('insertUnorderedList')}
          title="Bullet list"
          aria-label="Bullet list"
        >
          <List size={14} />
        </button>
        <button
          type="button"
          onClick={() => exec('insertOrderedList')}
          title="Numbered list"
          aria-label="Numbered list"
        >
          <ListOrdered size={14} />
        </button>
        <span className={styles.divider} />
        <button
          type="button"
          onClick={() => changeIndent(-1)}
          title="Decrease indent"
          aria-label="Decrease indent"
        >
          <IndentDecrease size={14} />
        </button>
        <button
          type="button"
          onClick={() => changeIndent(1)}
          title="Increase indent"
          aria-label="Increase indent"
        >
          <IndentIncrease size={14} />
        </button>
      </div>
      <div
        ref={editorRef}
        className={styles.editor}
        style={{ minHeight: editorMinHeight }}
        contentEditable
        role="textbox"
        aria-multiline="true"
        data-placeholder={placeholder}
        onInput={syncChange}
        onKeyDown={onEditorKeyDown}
        suppressContentEditableWarning
      />
    </div>
  )
}

/** True when HTML is empty or only whitespace / empty tags. */
export function isEmptyRichText(html: string | null | undefined): boolean {
  return richTextToPlain(html).length === 0
}

/** Strip tags for single-line list previews. */
export function richTextToPlain(html: string | null | undefined): string {
  if (!html) return ''
  return html
    .replace(/<br\s*\/?>/gi, ' ')
    .replace(/&nbsp;/gi, ' ')
    .replace(/<[^>]+>/g, '')
    .replace(/\s+/g, ' ')
    .trim()
}
