'use client'

import { useCallback, useEffect, useState } from 'react'
import { PagePurpose } from '@/components/common/PagePurpose'
import { PipelineStepper } from '@/components/ocr-pipeline/PipelineStepper'
import { StepOrientation } from '@/components/ocr-pipeline/StepOrientation'
import { StepDeskew } from '@/components/ocr-pipeline/StepDeskew'
import { StepDewarp } from '@/components/ocr-pipeline/StepDewarp'
import { StepCrop } from '@/components/ocr-pipeline/StepCrop'
import { StepStructureDetection } from '@/components/ocr-pipeline/StepStructureDetection'
import { StepRowDetection } from '@/components/ocr-pipeline/StepRowDetection'
import { StepWordRecognition } from '@/components/ocr-pipeline/StepWordRecognition'
import { OverlayReconstruction } from '@/components/ocr-overlay/OverlayReconstruction'
import { PaddleDirectStep } from '@/components/ocr-overlay/PaddleDirectStep'
import { GridEditor } from '@/components/grid-editor/GridEditor'
import { OVERLAY_PIPELINE_STEPS, PADDLE_DIRECT_STEPS, KOMBI_STEPS, DOCUMENT_CATEGORIES, dbStepToOverlayUi, type PipelineStep, type SessionListItem, type DocumentCategory } from './types'

const KLAUSUR_API = '/klausur-api'

export default function OcrOverlayPage() {
  const [mode, setMode] = useState<'pipeline' | 'paddle-direct' | 'kombi'>('pipeline')
  const [currentStep, setCurrentStep] = useState(0)
  const [sessionId, setSessionId] = useState<string | null>(null)
  const [sessionName, setSessionName] = useState<string>('')
  const [sessions, setSessions] = useState<SessionListItem[]>([])
  const [loadingSessions, setLoadingSessions] = useState(true)
  const [editingName, setEditingName] = useState<string | null>(null)
  const [editNameValue, setEditNameValue] = useState('')
  const [editingCategory, setEditingCategory] = useState<string | null>(null)
  const [activeCategory, setActiveCategory] = useState<DocumentCategory | undefined>(undefined)
  const [steps, setSteps] = useState<PipelineStep[]>(
    OVERLAY_PIPELINE_STEPS.map((s, i) => ({
      ...s,
      status: i === 0 ? 'active' : 'pending',
    })),
  )

  useEffect(() => {
    loadSessions()
  }, [])

  const loadSessions = async () => {
    setLoadingSessions(true)
    try {
      const res = await fetch(`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions`)
      if (res.ok) {
        const data = await res.json()
        // Filter to only show top-level sessions (no sub-sessions)
        setSessions((data.sessions || []).filter((s: SessionListItem) => !s.parent_session_id))
      }
    } catch (e) {
      console.error('Failed to load sessions:', e)
    } finally {
      setLoadingSessions(false)
    }
  }

  const openSession = useCallback(async (sid: string) => {
    try {
      const res = await fetch(`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sid}`)
      if (!res.ok) return
      const data = await res.json()

      setSessionId(sid)
      setSessionName(data.name || data.filename || '')
      setActiveCategory(data.document_category || undefined)

      // Check if this session was processed with paddle_direct, kombi, or rapid_kombi
      const ocrEngine = data.word_result?.ocr_engine
      const isPaddleDirect = ocrEngine === 'paddle_direct'
      const isKombi = ocrEngine === 'kombi' || ocrEngine === 'rapid_kombi'

      if (isPaddleDirect || isKombi) {
        const m = isKombi ? 'kombi' : 'paddle-direct'
        const baseSteps = isKombi ? KOMBI_STEPS : PADDLE_DIRECT_STEPS
        setMode(m)

        // For Kombi: if grid_editor_result exists, jump to grid editor step (6)
        // If word_result exists but no grid, jump to grid editor (6)
        // If structure_result exists, jump to kombi step (5)
        const hasGrid = isKombi && data.grid_editor_result
        const hasWords = isKombi && data.word_result
        const hasStructure = isKombi && data.structure_result
        const activeStep = hasGrid ? 6 : hasWords ? 6 : hasStructure ? 5 : 4
        setSteps(
          baseSteps.map((s, i) => ({
            ...s,
            status: i < activeStep ? 'completed' : i === activeStep ? 'active' : 'pending',
          })),
        )
        setCurrentStep(activeStep)
      } else {
        setMode('pipeline')
        // Map DB step to overlay UI step
        const dbStep = data.current_step || 1
        const uiStep = dbStepToOverlayUi(dbStep)

        setSteps(
          OVERLAY_PIPELINE_STEPS.map((s, i) => ({
            ...s,
            status: i < uiStep ? 'completed' : i === uiStep ? 'active' : 'pending',
          })),
        )
        setCurrentStep(uiStep)
      }
    } catch (e) {
      console.error('Failed to open session:', e)
    }
  }, [])

  const deleteSession = useCallback(async (sid: string) => {
    try {
      await fetch(`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sid}`, { method: 'DELETE' })
      setSessions((prev) => prev.filter((s) => s.id !== sid))
      if (sessionId === sid) {
        setSessionId(null)
        setCurrentStep(0)
        const baseSteps = mode === 'kombi' ? KOMBI_STEPS : mode === 'paddle-direct' ? PADDLE_DIRECT_STEPS : OVERLAY_PIPELINE_STEPS
        setSteps(baseSteps.map((s, i) => ({ ...s, status: i === 0 ? 'active' : 'pending' })))
      }
    } catch (e) {
      console.error('Failed to delete session:', e)
    }
  }, [sessionId, mode])

  const renameSession = useCallback(async (sid: string, newName: string) => {
    try {
      await fetch(`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sid}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name: newName }),
      })
      setSessions((prev) => prev.map((s) => (s.id === sid ? { ...s, name: newName } : s)))
      if (sessionId === sid) setSessionName(newName)
    } catch (e) {
      console.error('Failed to rename session:', e)
    }
    setEditingName(null)
  }, [sessionId])

  const updateCategory = useCallback(async (sid: string, category: DocumentCategory) => {
    try {
      await fetch(`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sid}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ document_category: category }),
      })
      setSessions((prev) => prev.map((s) => (s.id === sid ? { ...s, document_category: category } : s)))
      if (sessionId === sid) setActiveCategory(category)
    } catch (e) {
      console.error('Failed to update category:', e)
    }
    setEditingCategory(null)
  }, [sessionId])

  const handleStepClick = (index: number) => {
    if (index <= currentStep || steps[index].status === 'completed') {
      setCurrentStep(index)
    }
  }

  const goToStep = (step: number) => {
    setCurrentStep(step)
    setSteps((prev) =>
      prev.map((s, i) => ({
        ...s,
        status: i < step ? 'completed' : i === step ? 'active' : 'pending',
      })),
    )
  }

  const handleNext = () => {
    if (currentStep >= steps.length - 1) {
      // Last step completed — return to session list
      const baseSteps = mode === 'kombi' ? KOMBI_STEPS : mode === 'paddle-direct' ? PADDLE_DIRECT_STEPS : OVERLAY_PIPELINE_STEPS
      setSteps(baseSteps.map((s, i) => ({ ...s, status: i === 0 ? 'active' : 'pending' })))
      setCurrentStep(0)
      setSessionId(null)
      loadSessions()
      return
    }

    const nextStep = currentStep + 1
    setSteps((prev) =>
      prev.map((s, i) => {
        if (i === currentStep) return { ...s, status: 'completed' }
        if (i === nextStep) return { ...s, status: 'active' }
        return s
      }),
    )
    setCurrentStep(nextStep)
  }

  const handleOrientationComplete = (sid: string) => {
    setSessionId(sid)
    loadSessions()
    handleNext()
  }

  const handleNewSession = () => {
    setSessionId(null)
    setSessionName('')
    setCurrentStep(0)
    const baseSteps = mode === 'kombi' ? KOMBI_STEPS : mode === 'paddle-direct' ? PADDLE_DIRECT_STEPS : OVERLAY_PIPELINE_STEPS
    setSteps(baseSteps.map((s, i) => ({ ...s, status: i === 0 ? 'active' : 'pending' })))
  }

  const stepNames: Record<number, string> = {
    1: 'Orientierung',
    2: 'Begradigung',
    3: 'Entzerrung',
    4: 'Zuschneiden',
    5: 'Zeilen',
    6: 'Woerter',
    7: 'Overlay',
  }

  const reprocessFromStep = useCallback(async (uiStep: number) => {
    if (!sessionId) return
    // Map overlay UI step to DB step
    const dbStepMap: Record<number, number> = { 0: 2, 1: 3, 2: 4, 3: 5, 4: 7, 5: 8, 6: 9 }
    const dbStep = dbStepMap[uiStep] || uiStep + 1
    if (!confirm(`Ab Schritt ${uiStep + 1} (${stepNames[uiStep + 1] || '?'}) neu verarbeiten?`)) return
    try {
      const res = await fetch(`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/reprocess`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ from_step: dbStep }),
      })
      if (!res.ok) {
        const data = await res.json().catch(() => ({}))
        console.error('Reprocess failed:', data.detail || res.status)
        return
      }
      goToStep(uiStep)
    } catch (e) {
      console.error('Reprocess error:', e)
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [sessionId, goToStep])

  const renderStep = () => {
    if (mode === 'paddle-direct' || mode === 'kombi') {
      switch (currentStep) {
        case 0:
          return <StepOrientation sessionId={sessionId} onNext={handleOrientationComplete} />
        case 1:
          return <StepDeskew sessionId={sessionId} onNext={handleNext} />
        case 2:
          return <StepDewarp sessionId={sessionId} onNext={handleNext} />
        case 3:
          return <StepCrop sessionId={sessionId} onNext={handleNext} />
        case 4:
          if (mode === 'kombi') {
            return <StepStructureDetection sessionId={sessionId} onNext={handleNext} />
          }
          return <PaddleDirectStep sessionId={sessionId} onNext={handleNext} />
        case 5:
          return mode === 'kombi' ? (
            <PaddleDirectStep
              sessionId={sessionId}
              onNext={handleNext}
              endpoint="paddle-kombi"
              title="Kombi-Modus"
              description="PP-OCRv5 und Tesseract laufen parallel. Koordinaten werden gewichtet gemittelt fuer optimale Positionierung."
              icon="🔀"
              buttonLabel="PP-OCRv5 + Tesseract starten"
              runningLabel="PP-OCRv5 + Tesseract laufen..."
              engineKey="kombi"
            />
          ) : null
        case 6:
          return mode === 'kombi' ? (
            <GridEditor sessionId={sessionId} onNext={handleNext} />
          ) : null
        default:
          return null
      }
    }
    switch (currentStep) {
      case 0:
        return <StepOrientation sessionId={sessionId} onNext={handleOrientationComplete} />
      case 1:
        return <StepDeskew sessionId={sessionId} onNext={handleNext} />
      case 2:
        return <StepDewarp sessionId={sessionId} onNext={handleNext} />
      case 3:
        return <StepCrop sessionId={sessionId} onNext={handleNext} />
      case 4:
        return <StepRowDetection sessionId={sessionId} onNext={handleNext} />
      case 5:
        return <StepWordRecognition sessionId={sessionId} onNext={handleNext} goToStep={goToStep} skipHealGaps />
      case 6:
        return <OverlayReconstruction sessionId={sessionId} onNext={handleNext} />
      default:
        return null
    }
  }

  return (
    <div className="space-y-6">
      <PagePurpose
        title="OCR Overlay"
        purpose="Ganzseitige Overlay-Rekonstruktion: Scan begradigen, Zeilen und Woerter erkennen, dann pixelgenau ueber das Bild legen. Ohne Spaltenerkennung — ideal fuer Arbeitsblaetter."
        audience={['Entwickler']}
        architecture={{
          services: ['klausur-service (FastAPI)', 'OpenCV', 'Tesseract'],
          databases: ['PostgreSQL Sessions'],
        }}
        relatedPages={[
          { name: 'OCR Pipeline', href: '/ai/ocr-pipeline', description: 'Volle Pipeline mit Spalten' },
          { name: 'OCR Vergleich', href: '/ai/ocr-compare', description: 'Methoden-Vergleich' },
        ]}
        defaultCollapsed
      />

      {/* Session List */}
      <div className="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-4">
        <div className="flex items-center justify-between mb-3">
          <h3 className="text-sm font-medium text-gray-700 dark:text-gray-300">
            Sessions ({sessions.length})
          </h3>
          <button
            onClick={handleNewSession}
            className="text-xs px-3 py-1.5 bg-teal-600 text-white rounded-lg hover:bg-teal-700 transition-colors"
          >
            + Neue Session
          </button>
        </div>

        {loadingSessions ? (
          <div className="text-sm text-gray-400 py-2">Lade Sessions...</div>
        ) : sessions.length === 0 ? (
          <div className="text-sm text-gray-400 py-2">Noch keine Sessions vorhanden.</div>
        ) : (
          <div className="space-y-1.5 max-h-[320px] overflow-y-auto">
            {sessions.map((s) => {
              const catInfo = DOCUMENT_CATEGORIES.find(c => c.value === s.document_category)
              return (
                <div
                  key={s.id}
                  className={`relative flex items-start gap-3 px-3 py-2.5 rounded-lg text-sm transition-colors cursor-pointer ${
                    sessionId === s.id
                      ? 'bg-teal-50 dark:bg-teal-900/30 border border-teal-200 dark:border-teal-700'
                      : 'hover:bg-gray-50 dark:hover:bg-gray-700/50'
                  }`}
                >
                  {/* Thumbnail */}
                  <div
                    className="flex-shrink-0 w-12 h-12 rounded-md overflow-hidden bg-gray-100 dark:bg-gray-700"
                    onClick={() => openSession(s.id)}
                  >
                    {/* eslint-disable-next-line @next/next/no-img-element */}
                    <img
                      src={`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${s.id}/thumbnail?size=96`}
                      alt=""
                      className="w-full h-full object-cover"
                      loading="lazy"
                      onError={(e) => { (e.target as HTMLImageElement).style.display = 'none' }}
                    />
                  </div>

                  {/* Info */}
                  <div className="flex-1 min-w-0" onClick={() => openSession(s.id)}>
                    {editingName === s.id ? (
                      <input
                        autoFocus
                        value={editNameValue}
                        onChange={(e) => setEditNameValue(e.target.value)}
                        onBlur={() => renameSession(s.id, editNameValue)}
                        onKeyDown={(e) => {
                          if (e.key === 'Enter') renameSession(s.id, editNameValue)
                          if (e.key === 'Escape') setEditingName(null)
                        }}
                        onClick={(e) => e.stopPropagation()}
                        className="w-full px-1 py-0.5 text-sm border rounded dark:bg-gray-700 dark:border-gray-600"
                      />
                    ) : (
                      <div className="truncate font-medium text-gray-700 dark:text-gray-300">
                        {s.name || s.filename}
                      </div>
                    )}
                    <button
                      onClick={(e) => {
                        e.stopPropagation()
                        navigator.clipboard.writeText(s.id)
                        const btn = e.currentTarget
                        btn.textContent = 'Kopiert!'
                        setTimeout(() => { btn.textContent = `ID: ${s.id.slice(0, 8)}` }, 1500)
                      }}
                      className="text-[10px] font-mono text-gray-400 hover:text-teal-500 transition-colors"
                      title={`Volle ID: ${s.id} — Klick zum Kopieren`}
                    >
                      ID: {s.id.slice(0, 8)}
                    </button>
                    <div className="text-xs text-gray-400 flex gap-2 mt-0.5">
                      <span>{new Date(s.created_at).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: '2-digit', hour: '2-digit', minute: '2-digit' })}</span>
                    </div>
                  </div>

                  {/* Category Badge */}
                  <div className="flex flex-col gap-1 items-end flex-shrink-0" onClick={(e) => e.stopPropagation()}>
                    <button
                      onClick={() => setEditingCategory(editingCategory === s.id ? null : s.id)}
                      className={`text-[10px] px-1.5 py-0.5 rounded-full border transition-colors ${
                        catInfo
                          ? 'bg-teal-50 dark:bg-teal-900/30 border-teal-200 dark:border-teal-700 text-teal-700 dark:text-teal-300'
                          : 'bg-gray-50 dark:bg-gray-700 border-gray-200 dark:border-gray-600 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300'
                      }`}
                      title="Kategorie setzen"
                    >
                      {catInfo ? `${catInfo.icon} ${catInfo.label}` : '+ Kategorie'}
                    </button>
                  </div>

                  {/* Actions */}
                  <div className="flex flex-col gap-0.5 flex-shrink-0">
                    <button
                      onClick={(e) => {
                        e.stopPropagation()
                        setEditNameValue(s.name || s.filename)
                        setEditingName(s.id)
                      }}
                      className="p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
                      title="Umbenennen"
                    >
                      <svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
                        <path strokeLinecap="round" strokeLinejoin="round" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" />
                      </svg>
                    </button>
                    <button
                      onClick={(e) => {
                        e.stopPropagation()
                        if (confirm('Session loeschen?')) deleteSession(s.id)
                      }}
                      className="p-1 text-gray-400 hover:text-red-500"
                      title="Loeschen"
                    >
                      <svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
                        <path strokeLinecap="round" strokeLinejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
                      </svg>
                    </button>
                  </div>

                  {/* Category dropdown */}
                  {editingCategory === s.id && (
                    <div
                      className="absolute right-0 top-full mt-1 z-20 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg p-2 grid grid-cols-2 gap-1 w-64"
                      onClick={(e) => e.stopPropagation()}
                    >
                      {DOCUMENT_CATEGORIES.map((cat) => (
                        <button
                          key={cat.value}
                          onClick={() => updateCategory(s.id, cat.value)}
                          className={`text-xs px-2 py-1.5 rounded-md text-left transition-colors ${
                            s.document_category === cat.value
                              ? 'bg-teal-100 dark:bg-teal-900/40 text-teal-700 dark:text-teal-300'
                              : 'hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-600 dark:text-gray-400'
                          }`}
                        >
                          {cat.icon} {cat.label}
                        </button>
                      ))}
                    </div>
                  )}
                </div>
              )
            })}
          </div>
        )}
      </div>

      {/* Active session info */}
      {sessionId && sessionName && (
        <div className="flex items-center gap-3 text-sm text-gray-500 dark:text-gray-400">
          <span>Aktive Session: <span className="font-medium text-gray-700 dark:text-gray-300">{sessionName}</span></span>
          {activeCategory && (() => {
            const cat = DOCUMENT_CATEGORIES.find(c => c.value === activeCategory)
            return cat ? <span className="text-xs px-2 py-0.5 rounded-full bg-teal-50 dark:bg-teal-900/30 border border-teal-200 dark:border-teal-700 text-teal-700 dark:text-teal-300">{cat.icon} {cat.label}</span> : null
          })()}
        </div>
      )}

      {/* Mode Toggle */}
      <div className="flex items-center gap-1 bg-gray-100 dark:bg-gray-800 rounded-lg p-1 w-fit">
        <button
          onClick={() => {
            if (mode === 'pipeline') return
            setMode('pipeline')
            setCurrentStep(0)
            setSessionId(null)
            setSteps(OVERLAY_PIPELINE_STEPS.map((s, i) => ({ ...s, status: i === 0 ? 'active' : 'pending' })))
          }}
          className={`px-3 py-1.5 text-xs font-medium rounded-md transition-colors ${
            mode === 'pipeline'
              ? 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-200 shadow-sm'
              : 'text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300'
          }`}
        >
          Pipeline (7 Schritte)
        </button>
        <button
          onClick={() => {
            if (mode === 'paddle-direct') return
            setMode('paddle-direct')
            setCurrentStep(0)
            setSessionId(null)
            setSteps(PADDLE_DIRECT_STEPS.map((s, i) => ({ ...s, status: i === 0 ? 'active' : 'pending' })))
          }}
          className={`px-3 py-1.5 text-xs font-medium rounded-md transition-colors ${
            mode === 'paddle-direct'
              ? 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-200 shadow-sm'
              : 'text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300'
          }`}
        >
          PP-OCRv5 Direct (5 Schritte)
        </button>
        <button
          onClick={() => {
            if (mode === 'kombi') return
            setMode('kombi')
            setCurrentStep(0)
            setSessionId(null)
            setSteps(KOMBI_STEPS.map((s, i) => ({ ...s, status: i === 0 ? 'active' : 'pending' })))
          }}
          className={`px-3 py-1.5 text-xs font-medium rounded-md transition-colors ${
            mode === 'kombi'
              ? 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-200 shadow-sm'
              : 'text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300'
          }`}
        >
          Kombi (7 Schritte)
        </button>
      </div>

      <PipelineStepper
        steps={steps}
        currentStep={currentStep}
        onStepClick={handleStepClick}
        onReprocess={mode === 'pipeline' && sessionId != null ? reprocessFromStep : undefined}
      />

      <div className="min-h-[400px]">{renderStep()}</div>
    </div>
  )
}
