'use client'

import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import type { GridResult, GridCell, WordEntry } from '@/app/(admin)/ai/ocr-pipeline/types'

const KLAUSUR_API = '/klausur-api'

interface StepReconstructionProps {
  sessionId: string | null
  onNext: () => void
}

interface EditableCell {
  cellId: string
  text: string
  originalText: string
  bboxPct: { x: number; y: number; w: number; h: number }
  colType: string
  rowIndex: number
  colIndex: number
}

export function StepReconstruction({ sessionId, onNext }: StepReconstructionProps) {
  const [status, setStatus] = useState<'loading' | 'ready' | 'saving' | 'saved' | 'error'>('loading')
  const [error, setError] = useState('')
  const [cells, setCells] = useState<EditableCell[]>([])
  const [editedTexts, setEditedTexts] = useState<Map<string, string>>(new Map())
  const [zoom, setZoom] = useState(100)
  const [containerSize, setContainerSize] = useState<{ w: number; h: number } | null>(null)

  const containerRef = useRef<HTMLDivElement>(null)
  const imageRef = useRef<HTMLImageElement>(null)

  // Load session data on mount
  useEffect(() => {
    if (!sessionId) return
    loadSessionData()
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [sessionId])

  // Track container size for font scaling
  useEffect(() => {
    if (!containerRef.current) return
    const observer = new ResizeObserver((entries) => {
      for (const entry of entries) {
        setContainerSize({ w: entry.contentRect.width, h: entry.contentRect.height })
      }
    })
    observer.observe(containerRef.current)
    return () => observer.disconnect()
  }, [])

  const loadSessionData = async () => {
    if (!sessionId) return
    setStatus('loading')
    try {
      const res = await fetch(`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}`)
      if (!res.ok) throw new Error(`HTTP ${res.status}`)
      const data = await res.json()

      const wordResult: GridResult | undefined = data.word_result
      if (!wordResult) {
        setError('Keine Worterkennungsdaten gefunden. Bitte zuerst Schritt 5 abschliessen.')
        setStatus('error')
        return
      }

      // Build editable cells from grid cells
      const gridCells: GridCell[] = wordResult.cells || []
      const editableCells: EditableCell[] = gridCells
        .filter(c => c.text.trim() !== '')
        .map(c => ({
          cellId: c.cell_id,
          text: c.text,
          originalText: c.text,
          bboxPct: c.bbox_pct,
          colType: c.col_type,
          rowIndex: c.row_index,
          colIndex: c.col_index,
        }))

      setCells(editableCells)
      setStatus('ready')
    } catch (e: unknown) {
      setError(e instanceof Error ? e.message : String(e))
      setStatus('error')
    }
  }

  const handleTextChange = useCallback((cellId: string, newText: string) => {
    setEditedTexts(prev => {
      const next = new Map(prev)
      next.set(cellId, newText)
      return next
    })
  }, [])

  const getDisplayText = useCallback((cell: EditableCell): string => {
    return editedTexts.get(cell.cellId) ?? cell.text
  }, [editedTexts])

  const isEdited = useCallback((cell: EditableCell): boolean => {
    const edited = editedTexts.get(cell.cellId)
    return edited !== undefined && edited !== cell.originalText
  }, [editedTexts])

  const changedCount = useMemo(() => {
    let count = 0
    for (const cell of cells) {
      if (isEdited(cell)) count++
    }
    return count
  }, [cells, isEdited])

  // Sort cells for tab navigation: by row, then by column
  const sortedCellIds = useMemo(() => {
    return [...cells]
      .sort((a, b) => a.rowIndex !== b.rowIndex ? a.rowIndex - b.rowIndex : a.colIndex - b.colIndex)
      .map(c => c.cellId)
  }, [cells])

  const handleKeyDown = useCallback((e: React.KeyboardEvent, cellId: string) => {
    if (e.key === 'Tab') {
      e.preventDefault()
      const idx = sortedCellIds.indexOf(cellId)
      const nextIdx = e.shiftKey ? idx - 1 : idx + 1
      if (nextIdx >= 0 && nextIdx < sortedCellIds.length) {
        const nextId = sortedCellIds[nextIdx]
        const el = document.getElementById(`cell-${nextId}`)
        el?.focus()
      }
    }
  }, [sortedCellIds])

  const saveReconstruction = useCallback(async () => {
    if (!sessionId) return
    setStatus('saving')
    try {
      const cellUpdates = Array.from(editedTexts.entries())
        .filter(([cellId, text]) => {
          const cell = cells.find(c => c.cellId === cellId)
          return cell && text !== cell.originalText
        })
        .map(([cellId, text]) => ({ cell_id: cellId, text }))

      if (cellUpdates.length === 0) {
        // Nothing changed, just advance
        setStatus('saved')
        return
      }

      const res = await fetch(`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/reconstruction`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ cells: cellUpdates }),
      })

      if (!res.ok) {
        const data = await res.json().catch(() => ({}))
        throw new Error(data.detail || `HTTP ${res.status}`)
      }

      setStatus('saved')
    } catch (e: unknown) {
      setError(e instanceof Error ? e.message : String(e))
      setStatus('error')
    }
  }, [sessionId, editedTexts, cells])

  const dewarpedUrl = sessionId
    ? `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/image/dewarped`
    : ''

  const colTypeColor = (colType: string): string => {
    const colors: Record<string, string> = {
      column_en: 'border-blue-400/40 focus:border-blue-500',
      column_de: 'border-green-400/40 focus:border-green-500',
      column_example: 'border-orange-400/40 focus:border-orange-500',
      column_text: 'border-purple-400/40 focus:border-purple-500',
    }
    return colors[colType] || 'border-gray-400/40 focus:border-gray-500'
  }

  if (!sessionId) {
    return <div className="text-center py-12 text-gray-400">Bitte zuerst eine Session auswaehlen.</div>
  }

  if (status === 'loading') {
    return (
      <div className="flex items-center gap-3 justify-center py-12">
        <div className="animate-spin rounded-full h-5 w-5 border-b-2 border-teal-500" />
        <span className="text-gray-500">Rekonstruktionsdaten werden geladen...</span>
      </div>
    )
  }

  if (status === 'error') {
    return (
      <div className="flex flex-col items-center justify-center py-12 text-center">
        <div className="text-5xl mb-4">⚠️</div>
        <h3 className="text-lg font-medium text-red-600 dark:text-red-400 mb-2">Fehler</h3>
        <p className="text-sm text-gray-500 dark:text-gray-400 max-w-lg mb-4">{error}</p>
        <div className="flex gap-3">
          <button onClick={() => { setError(''); loadSessionData() }}
            className="px-5 py-2 bg-teal-600 text-white rounded-lg hover:bg-teal-700 transition-colors text-sm">
            Erneut versuchen
          </button>
          <button onClick={onNext}
            className="px-5 py-2 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors text-sm">
            Ueberspringen →
          </button>
        </div>
      </div>
    )
  }

  if (status === 'saved') {
    return (
      <div className="flex flex-col items-center justify-center py-12 text-center">
        <div className="text-5xl mb-4">✅</div>
        <h3 className="text-lg font-medium text-gray-700 dark:text-gray-300 mb-2">Rekonstruktion gespeichert</h3>
        <p className="text-sm text-gray-500 dark:text-gray-400 mb-6">
          {changedCount > 0 ? `${changedCount} Zellen wurden aktualisiert.` : 'Keine Aenderungen vorgenommen.'}
        </p>
        <button onClick={onNext}
          className="px-6 py-2.5 bg-teal-600 text-white rounded-lg hover:bg-teal-700 transition-colors font-medium">
          Weiter →
        </button>
      </div>
    )
  }

  return (
    <div className="space-y-3">
      {/* Toolbar */}
      <div className="flex items-center justify-between bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 px-3 py-2">
        <div className="flex items-center gap-2">
          <h3 className="text-sm font-medium text-gray-700 dark:text-gray-300">
            Schritt 7: Rekonstruktion
          </h3>
          <span className="text-xs text-gray-400">
            {cells.length} Zellen · {changedCount} geaendert
          </span>
        </div>
        <div className="flex items-center gap-2">
          {/* Zoom controls */}
          <button
            onClick={() => setZoom(z => Math.max(50, z - 25))}
            className="px-2 py-1 text-xs border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-50 dark:hover:bg-gray-700"
          >
            −
          </button>
          <span className="text-xs text-gray-500 w-10 text-center">{zoom}%</span>
          <button
            onClick={() => setZoom(z => Math.min(200, z + 25))}
            className="px-2 py-1 text-xs border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-50 dark:hover:bg-gray-700"
          >
            +
          </button>
          <button
            onClick={() => setZoom(100)}
            className="px-2 py-1 text-xs border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-50 dark:hover:bg-gray-700"
          >
            Fit
          </button>

          <div className="w-px h-5 bg-gray-300 dark:bg-gray-600 mx-1" />

          <button
            onClick={saveReconstruction}
            disabled={status === 'saving'}
            className="px-4 py-1.5 text-xs bg-teal-600 text-white rounded-lg hover:bg-teal-700 disabled:opacity-50 transition-colors font-medium"
          >
            {status === 'saving' ? 'Speichert...' : 'Speichern'}
          </button>
        </div>
      </div>

      {/* Reconstruction canvas */}
      <div className="border rounded-lg overflow-auto dark:border-gray-700 bg-gray-100 dark:bg-gray-900" style={{ maxHeight: '75vh' }}>
        <div
          ref={containerRef}
          className="relative inline-block"
          style={{ transform: `scale(${zoom / 100})`, transformOrigin: 'top left' }}
        >
          {/* Background image at reduced opacity */}
          {/* eslint-disable-next-line @next/next/no-img-element */}
          <img
            ref={imageRef}
            src={dewarpedUrl}
            alt="Dewarped"
            className="block"
            style={{ opacity: 0.3 }}
          />

          {/* Editable text fields at bbox positions */}
          {cells.map((cell) => {
            const displayText = getDisplayText(cell)
            const edited = isEdited(cell)

            return (
              <input
                key={cell.cellId}
                id={`cell-${cell.cellId}`}
                type="text"
                value={displayText}
                onChange={(e) => handleTextChange(cell.cellId, e.target.value)}
                onKeyDown={(e) => handleKeyDown(e, cell.cellId)}
                className={`absolute bg-transparent text-black dark:text-white border px-0.5 outline-none transition-colors ${
                  colTypeColor(cell.colType)
                } ${edited ? 'border-green-500 bg-green-50/30 dark:bg-green-900/20' : ''}`}
                style={{
                  left: `${cell.bboxPct.x}%`,
                  top: `${cell.bboxPct.y}%`,
                  width: `${cell.bboxPct.w}%`,
                  height: `${cell.bboxPct.h}%`,
                  fontSize: `${Math.max(8, Math.min(16, (cell.bboxPct.h / 100) * (containerSize?.h || 800) * 0.6))}px`,
                  lineHeight: '1',
                }}
                title={`${cell.cellId} (${cell.colType})`}
              />
            )
          })}
        </div>
      </div>

      {/* Bottom action */}
      <div className="flex justify-end">
        <button
          onClick={() => {
            if (changedCount > 0) {
              saveReconstruction()
            } else {
              onNext()
            }
          }}
          className="px-6 py-2.5 bg-teal-600 text-white rounded-lg hover:bg-teal-700 transition-colors font-medium text-sm"
        >
          {changedCount > 0 ? 'Speichern & Weiter →' : 'Weiter →'}
        </button>
      </div>
    </div>
  )
}
