'use client'

import { Node, mergeAttributes } from '@tiptap/core'
import { ReactNodeViewRenderer, NodeViewWrapper, NodeViewContent } from '@tiptap/react'
import { Trash2, X, FunctionSquare, Sparkles, Loader2 } from 'lucide-react'
import { useState, useEffect, useRef } from 'react'
import { cn } from '@/lib/utils'
import { useLanguage } from '@/lib/i18n'
import katex from 'katex'

function renderKatex(latex: string, display: boolean): { html: string } {
  try {
    const html = katex.renderToString(latex, {
      displayMode: display,
      throwOnError: false,
      errorColor: '#ef4444',
    })
    return { html }
  } catch {
    return { html: '' }
  }
}

const MATH_BUTTONS: Array<{ label: string; insert: string; title: string }> = [
  { label: '½', insert: '\\frac{}{}', title: 'Fraction' },
  { label: '√', insert: '\\sqrt{}', title: 'Racine' },
  { label: '∑', insert: '\\sum_{}^{}', title: 'Somme' },
  { label: '∫', insert: '\\int_{}^{}', title: 'Intégrale' },
  { label: 'x²', insert: '^{}', title: 'Puissance' },
  { label: 'x₂', insert: '_{}', title: 'Indice' },
  { label: '×', insert: '\\times', title: 'Multiplication' },
  { label: '÷', insert: '\\div', title: 'Division' },
  { label: '±', insert: '\\pm', title: 'Plus ou moins' },
  { label: '≤', insert: '\\leq', title: 'Inférieur ou égal' },
  { label: '≥', insert: '\\geq', title: 'Supérieur ou égal' },
  { label: '≠', insert: '\\neq', title: 'Différent' },
  { label: '→', insert: '\\rightarrow', title: 'Flèche droite' },
  { label: '∞', insert: '\\infty', title: 'Infini' },
  { label: 'α', insert: '\\alpha', title: 'Alpha' },
  { label: 'β', insert: '\\beta', title: 'Beta' },
  { label: 'γ', insert: '\\gamma', title: 'Gamma' },
  { label: 'π', insert: '\\pi', title: 'Pi' },
  { label: 'θ', insert: '\\theta', title: 'Theta' },
  { label: 'Δ', insert: '\\Delta', title: 'Delta' },
]

const MathEquationView = ({ node, updateAttributes, deleteNode, selected }: any) => {
  const { t } = useLanguage()
  const latex = node.attrs.latex || ''
  const [editing, setEditing] = useState(!latex)
  const [input, setInput] = useState(latex)
  const [aiLoading, setAiLoading] = useState(false)
  const [aiInput, setAiInput] = useState('')
  const [showAi, setShowAi] = useState(false)
  const inputRef = useRef<HTMLTextAreaElement>(null)
  const renderRef = useRef<HTMLDivElement>(null)

  const { html } = renderKatex(latex, true)

  useEffect(() => {
    if (editing && inputRef.current) inputRef.current.focus()
  }, [editing])

  useEffect(() => {
    if (renderRef.current && html) renderRef.current.innerHTML = html
  }, [html])

  const commit = () => {
    updateAttributes({ latex: input })
    if (input.trim()) setEditing(false)
  }

  const insertSymbol = (symbol: string) => {
    const el = inputRef.current
    if (!el) { setInput(prev => prev + symbol); return }
    const start = el.selectionStart
    const end = el.selectionEnd
    const newVal = input.slice(0, start) + symbol + input.slice(end)
    setInput(newVal)
    setTimeout(() => {
      el.focus()
      const cursorPos = start + symbol.length
      if (symbol.includes('{}')) {
        const braceIdx = symbol.indexOf('{')
        el.setSelectionRange(start + braceIdx + 1, start + braceIdx + 1)
      } else {
        el.setSelectionRange(cursorPos, cursorPos)
      }
    }, 0)
  }

  const handleAiGenerate = async () => {
    if (!aiInput.trim()) return
    setAiLoading(true)
    try {
      const res = await fetch('/api/ai/math-from-text', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ description: aiInput }),
      })
      const data = await res.json()
      if (res.ok && data.latex) {
        setInput(data.latex)
        setShowAi(false)
        setAiInput('')
      }
    } catch (e) {
      console.error(e)
    } finally {
      setAiLoading(false)
    }
  }

  const livePreview = renderKatex(input, true).html

  return (
    <NodeViewWrapper className="math-block my-3" dir="auto" data-selected={selected}>
      {editing ? (
        <div className="rounded-xl border border-border bg-card p-3 space-y-2">
          {/* Toolbar */}
          <div className="flex flex-wrap gap-1 pb-2 border-b border-border/30">
            {MATH_BUTTONS.map(btn => (
              <button
                key={btn.label}
                type="button"
                onClick={() => insertSymbol(btn.insert)}
                className="w-7 h-7 flex items-center justify-center rounded-md text-sm hover:bg-muted transition-colors border border-border/30 font-serif"
                title={btn.title}
              >
                {btn.label}
              </button>
            ))}
          </div>

          {/* AI generation */}
          {showAi ? (
            <div className="flex items-center gap-1.5 rounded-lg bg-brand-accent/5 border border-brand-accent/20 p-2">
              <Sparkles size={14} className="text-brand-accent flex-shrink-0" />
              <input
                type="text"
                value={aiInput}
                onChange={(e) => setAiInput(e.target.value)}
                onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); handleAiGenerate() } }}
                placeholder={t('richTextEditor.mathAiPlaceholder')}
                className="flex-1 min-w-0 bg-transparent text-sm outline-none"
                autoFocus
              />
              {aiLoading ? (
                <Loader2 size={14} className="animate-spin text-brand-accent" />
              ) : (
                <button
                  type="button"
                  onClick={handleAiGenerate}
                  disabled={!aiInput.trim()}
                  className="text-xs font-medium text-brand-accent hover:underline disabled:opacity-40"
                >
                  {t('richTextEditor.mathConfirm')}
                </button>
              )}
              <button type="button" onClick={() => setShowAi(false)} className="p-0.5 text-muted-foreground hover:text-foreground">
                <X size={14} />
              </button>
            </div>
          ) : (
            <button
              type="button"
              onClick={() => setShowAi(true)}
              className="flex items-center gap-1.5 text-[11px] text-brand-accent hover:underline font-medium"
            >
              <Sparkles size={12} />
              {t('richTextEditor.mathAi')}
            </button>
          )}

          {/* LaTeX input */}
          <textarea
            ref={inputRef}
            value={input}
            onChange={(e) => setInput(e.target.value)}
            onKeyDown={(e) => {
              if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) { e.preventDefault(); commit() }
              if (e.key === 'Escape' && latex) { setInput(latex); setEditing(false) }
            }}
            placeholder={t('richTextEditor.mathPlaceholder')}
            className="w-full rounded-lg border border-border bg-background px-3 py-2 font-mono text-sm resize-none"
            rows={2}
          />

          {/* Live preview */}
          {input.trim() && (
            <div className="rounded-lg bg-muted/30 px-4 py-3 overflow-x-auto text-center" ref={(el) => { if (el) el.innerHTML = livePreview }} />
          )}

          {/* Actions */}
          <div className="flex items-center justify-between pt-1">
            <div className="flex items-center gap-0.5">
              {latex && (
                <button onClick={() => { setInput(latex); setEditing(false) }} className="p-1 rounded hover:bg-muted text-muted-foreground" title={t('richTextEditor.mathCancel')}>
                  <X className="h-3.5 w-3.5" />
                </button>
              )}
              <button onClick={deleteNode} className="p-1 rounded hover:bg-destructive/10 text-muted-foreground hover:text-destructive" title={t('richTextEditor.mathDelete')}>
                <Trash2 className="h-3.5 w-3.5" />
              </button>
            </div>
            <button
              onClick={commit}
              disabled={!input.trim()}
              className="px-3 py-1 text-xs rounded-md bg-brand-accent text-white hover:bg-brand-accent/90 disabled:opacity-40 transition-colors font-medium"
            >
              {t('richTextEditor.mathConfirm')}
            </button>
          </div>
        </div>
      ) : (
        <div className={cn('group relative rounded-xl border bg-card overflow-hidden', selected ? 'border-primary/40 ring-2 ring-primary/20' : 'border-border')}>
          <div ref={renderRef} className="px-6 py-4 overflow-x-auto text-center" />
          <div className="absolute top-1.5 right-1.5 flex items-center gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity">
            <button onClick={() => setEditing(true)} className="px-2 py-0.5 text-[10px] rounded-md bg-background/80 backdrop-blur hover:bg-muted text-muted-foreground">
              {t('richTextEditor.mathEdit')}
            </button>
            <button onClick={deleteNode} className="p-1 rounded-md bg-background/80 backdrop-blur hover:bg-destructive/10 text-muted-foreground hover:text-destructive">
              <Trash2 className="h-3.5 w-3.5" />
            </button>
          </div>
        </div>
      )}
    </NodeViewWrapper>
  )
}

// Inline math node — renders $x^2$ inline within text
const InlineMathView = ({ node }: any) => {
  const ref = useRef<HTMLSpanElement>(null)
  const latex = node.attrs.latex || ''

  useEffect(() => {
    if (ref.current) {
      const { html } = renderKatex(latex, false)
      ref.current.innerHTML = html
    }
  }, [latex])

  return <NodeViewWrapper as="span" ref={ref} className="inline-math" />
}

export const MathEquationExtension = Node.create({
  name: 'mathEquationBlock',
  group: 'block',
  atom: true,
  defining: true,

  addAttributes() {
    return {
      latex: {
        default: '',
        parseHTML: (el) => el.getAttribute('data-latex') || el.textContent || '',
        renderHTML: (attrs) => ({ 'data-latex': attrs.latex }),
      },
    }
  },

  parseHTML() {
    return [
      { tag: 'div[data-type="math-equation"]' },
    ]
  },

  renderHTML({ node, HTMLAttributes }) {
    return [
      'div',
      mergeAttributes(HTMLAttributes, {
        'data-type': 'math-equation',
        'data-latex': node.attrs.latex,
        class: 'math-equation-block',
      }),
      node.attrs.latex || '',
    ]
  },

  addNodeView() {
    return ReactNodeViewRenderer(MathEquationView)
  },

  addInputRules() {
    return [
      {
        find: /\$\$([^$]+)\$\$$/,
        handler: ({ state, range, match }) => {
          const latex = match[1]
          const tr = state.tr
          tr.deleteRange(range.from, range.to)
          tr.insert(range.from, state.schema.nodes.mathEquationBlock.create({ latex }))
        },
      },
    ]
  },

  addKeyboardShortcuts() {
    return {
      'Mod-Shift-M': () => this.editor.commands.insertContent({
        type: this.name,
        attrs: { latex: '' },
      }),
    }
  },
})

// Inline math mark — detects $...$ in text
export const InlineMathExtension = Node.create({
  name: 'inlineMath',
  group: 'inline',
  inline: true,
  atom: true,

  addAttributes() {
    return {
      latex: {
        default: '',
        parseHTML: (el) => el.getAttribute('data-latex') || el.textContent || '',
        renderHTML: (attrs) => ({ 'data-latex': attrs.latex }),
      },
    }
  },

  parseHTML() {
    return [{ tag: 'span[data-type="inline-math"]' }]
  },

  renderHTML({ node, HTMLAttributes }) {
    return [
      'span',
      mergeAttributes(HTMLAttributes, {
        'data-type': 'inline-math',
        'data-latex': node.attrs.latex,
        class: 'inline-math',
      }),
      node.attrs.latex || '',
    ]
  },

  addNodeView() {
    return ReactNodeViewRenderer(InlineMathView)
  },

  addInputRules() {
    return [
      {
        find: /(?:^|\s)\$([^$\n]+)\$$/,
        handler: ({ state, range, match }) => {
          const fullMatch = match[0]
          const latex = match[1]
          const leadingSpace = fullMatch.startsWith(' ') ? ' ' : ''
          const start = range.from + (leadingSpace ? 1 : 0)

          const tr = state.tr
          tr.deleteRange(range.from, range.to)
          tr.insert(range.from, [
            ...(leadingSpace ? [state.schema.text(' ')] : []),
            state.schema.nodes.inlineMath.create({ latex }),
          ])
        },
      },
    ]
  },
})

export function insertMathEquation(editor: any) {
  editor.chain().focus().insertContent({
    type: 'mathEquationBlock',
    attrs: { latex: '' },
  }).run()
}
