'use client'

import { useCallback, useEffect, useRef, useState } from 'react'
import type { ImageStyle } from '@/app/(admin)/ai/ocr-kombi/types'
import type {
  SessionData, ImageRegionWithState, GroundTruthStatus,
} from './ground-truth-types'
import { KLAUSUR_API } from './ground-truth-types'

export function useGroundTruthSession(sessionId: string | null) {
  const [status, setStatus] = useState<GroundTruthStatus>('loading')
  const [error, setError] = useState('')
  const [session, setSession] = useState<SessionData | null>(null)
  const [imageRegions, setImageRegions] = useState<ImageRegionWithState[]>([])
  const [detecting, setDetecting] = useState(false)
  const [zoom, setZoom] = useState(100)
  const [syncScroll, setSyncScroll] = useState(true)
  const [notes, setNotes] = useState('')
  const [score, setScore] = useState<number | null>(null)
  const [drawingRegion, setDrawingRegion] = useState(false)
  const [dragStart, setDragStart] = useState<{ x: number; y: number } | null>(null)
  const [dragEnd, setDragEnd] = useState<{ x: number; y: number } | null>(null)
  const [isGroundTruth, setIsGroundTruth] = useState(false)
  const [gtSaving, setGtSaving] = useState(false)
  const [gtMessage, setGtMessage] = useState('')

  const leftPanelRef = useRef<HTMLDivElement>(null)
  const rightPanelRef = useRef<HTMLDivElement>(null)
  const reconRef = useRef<HTMLDivElement>(null)
  const [reconWidth, setReconWidth] = useState(0)

  // Track reconstruction container width for font size calculation
  useEffect(() => {
    const el = reconRef.current
    if (!el) return
    const obs = new ResizeObserver(entries => {
      for (const entry of entries) setReconWidth(entry.contentRect.width)
    })
    obs.observe(el)
    return () => obs.disconnect()
  }, [session])

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

      const wordResult = data.word_result || {}
      setSession({
        cells: wordResult.cells || [],
        columnsUsed: wordResult.columns_used || [],
        imageWidth: wordResult.image_width || data.image_width || 800,
        imageHeight: wordResult.image_height || data.image_height || 600,
        originalImageUrl: data.original_image_url
          ? `${KLAUSUR_API}${data.original_image_url}`
          : `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/image/original`,
      })

      // Check if session has ground truth reference
      const gt = data.ground_truth
      setIsGroundTruth(!!gt?.build_grid_reference)

      // Load existing validation data
      const valResp = await fetch(`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/reconstruction/validation`)
      if (valResp.ok) {
        const valData = await valResp.json()
        const validation = valData.validation
        if (validation) {
          setImageRegions(validation.image_regions || [])
          setNotes(validation.notes || '')
          setScore(validation.score ?? null)
        }
      }

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

  // Load session data
  useEffect(() => {
    if (!sessionId) return
    loadSessionData()
  }, [sessionId, loadSessionData])

  // Sync scroll between panels
  const handleScroll = useCallback((source: 'left' | 'right') => {
    if (!syncScroll) return
    const from = source === 'left' ? leftPanelRef.current : rightPanelRef.current
    const to = source === 'left' ? rightPanelRef.current : leftPanelRef.current
    if (from && to) {
      to.scrollTop = from.scrollTop
      to.scrollLeft = from.scrollLeft
    }
  }, [syncScroll])

  // Detect images via VLM
  const handleDetectImages = useCallback(async () => {
    if (!sessionId) return
    setDetecting(true)
    try {
      const resp = await fetch(
        `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/reconstruction/detect-images`,
        { method: 'POST' }
      )
      if (!resp.ok) throw new Error(`Detection failed: ${resp.status}`)
      const data = await resp.json()
      setImageRegions(data.regions || [])
    } catch (e) {
      setError(e instanceof Error ? e.message : String(e))
    } finally {
      setDetecting(false)
    }
  }, [sessionId])

  // Generate image for a region
  const handleGenerateImage = useCallback(async (index: number) => {
    if (!sessionId) return
    const region = imageRegions[index]
    if (!region) return

    setImageRegions(prev => prev.map((r, i) => i === index ? { ...r, generating: true } : r))

    try {
      const resp = await fetch(
        `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/reconstruction/generate-image`,
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            region_index: index,
            prompt: region.prompt,
            style: region.style,
          }),
        }
      )
      if (!resp.ok) throw new Error(`Generation failed: ${resp.status}`)
      const data = await resp.json()

      setImageRegions(prev => prev.map((r, i) =>
        i === index ? { ...r, image_b64: data.image_b64, generating: false } : r
      ))
    } catch (e) {
      setImageRegions(prev => prev.map((r, i) => i === index ? { ...r, generating: false } : r))
      setError(e instanceof Error ? e.message : String(e))
    }
  }, [sessionId, imageRegions])

  // Save validation
  const handleSave = useCallback(async () => {
    if (!sessionId) {
      setError('Keine Session-ID vorhanden')
      return
    }
    setStatus('saving')
    setError('')
    try {
      const resp = await fetch(
        `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/reconstruction/validate`,
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ notes, score: score ?? 0 }),
        }
      )
      if (!resp.ok) {
        const body = await resp.text().catch(() => '')
        throw new Error(`Speichern fehlgeschlagen (${resp.status}): ${body}`)
      }
      setStatus('saved')
    } catch (e) {
      setError(e instanceof Error ? e.message : String(e))
      setStatus('ready')
    }
  }, [sessionId, notes, score])

  // Mark/update ground truth reference
  const handleMarkGroundTruth = useCallback(async () => {
    if (!sessionId) return
    setGtSaving(true)
    setGtMessage('')
    try {
      const resp = await fetch(
        `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/mark-ground-truth?pipeline=ocr-pipeline`,
        { method: 'POST' }
      )
      if (!resp.ok) {
        const body = await resp.text().catch(() => '')
        throw new Error(`Ground Truth fehlgeschlagen (${resp.status}): ${body}`)
      }
      const data = await resp.json()
      setIsGroundTruth(true)
      setGtMessage(`Ground Truth gespeichert (${data.cells_saved} Zellen)`)
      setTimeout(() => setGtMessage(''), 5000)
    } catch (e) {
      setGtMessage(e instanceof Error ? e.message : String(e))
    } finally {
      setGtSaving(false)
    }
  }, [sessionId])

  // Handle manual region drawing on reconstruction
  const handleReconMouseDown = useCallback((e: React.MouseEvent<HTMLDivElement>) => {
    if (!drawingRegion) return
    const rect = e.currentTarget.getBoundingClientRect()
    const x = ((e.clientX - rect.left) / rect.width) * 100
    const y = ((e.clientY - rect.top) / rect.height) * 100
    setDragStart({ x, y })
    setDragEnd({ x, y })
  }, [drawingRegion])

  const handleReconMouseMove = useCallback((e: React.MouseEvent<HTMLDivElement>) => {
    if (!dragStart) return
    const rect = e.currentTarget.getBoundingClientRect()
    const x = ((e.clientX - rect.left) / rect.width) * 100
    const y = ((e.clientY - rect.top) / rect.height) * 100
    setDragEnd({ x, y })
  }, [dragStart])

  const handleReconMouseUp = useCallback(() => {
    if (!dragStart || !dragEnd) return
    const x = Math.min(dragStart.x, dragEnd.x)
    const y = Math.min(dragStart.y, dragEnd.y)
    const w = Math.abs(dragEnd.x - dragStart.x)
    const h = Math.abs(dragEnd.y - dragStart.y)

    if (w > 2 && h > 2) {
      setImageRegions(prev => [...prev, {
        bbox_pct: { x, y, w, h },
        prompt: '',
        description: 'Manually selected region',
        image_b64: null,
        style: 'educational' as ImageStyle,
      }])
    }

    setDragStart(null)
    setDragEnd(null)
    setDrawingRegion(false)
  }, [dragStart, dragEnd])

  const handleRemoveRegion = useCallback((index: number) => {
    setImageRegions(prev => prev.filter((_, i) => i !== index))
  }, [])

  return {
    // State
    status, error, session, imageRegions, detecting, zoom, syncScroll,
    notes, score, drawingRegion, dragStart, dragEnd,
    isGroundTruth, gtSaving, gtMessage, reconWidth,
    // Refs
    leftPanelRef, rightPanelRef, reconRef,
    // Setters
    setError, setZoom, setSyncScroll, setNotes, setScore,
    setDrawingRegion, setImageRegions,
    // Handlers
    loadSessionData, handleScroll, handleDetectImages, handleGenerateImage,
    handleSave, handleMarkGroundTruth,
    handleReconMouseDown, handleReconMouseMove, handleReconMouseUp,
    handleRemoveRegion,
  }
}
