import { useCallback, useEffect, useRef } from 'react'
import type { StructuredGrid } from './types'
import type { IpaMode, SyllableMode } from './gridEditorTypes'
import { KLAUSUR_API } from './gridEditorTypes'

interface ApiDeps {
  sessionId: string | null
  ipaMode: IpaMode
  syllableMode: SyllableMode
  ocrEnhance: boolean
  ocrMaxCols: number
  ocrMinConf: number
  visionFusion: boolean
  documentCategory: string
  setGrid: React.Dispatch<React.SetStateAction<StructuredGrid | null>>
  setLoading: React.Dispatch<React.SetStateAction<boolean>>
  setSaving: React.Dispatch<React.SetStateAction<boolean>>
  setError: React.Dispatch<React.SetStateAction<string | null>>
  setDirty: React.Dispatch<React.SetStateAction<boolean>>
  grid: StructuredGrid | null
  undoStack: React.MutableRefObject<string[]>
  redoStack: React.MutableRefObject<string[]>
}

export function useGridEditorApi(deps: ApiDeps) {
  const {
    sessionId,
    ipaMode,
    syllableMode,
    ocrEnhance,
    ocrMaxCols,
    ocrMinConf,
    visionFusion,
    documentCategory,
    setGrid,
    setLoading,
    setSaving,
    setError,
    setDirty,
    grid,
    undoStack,
    redoStack,
  } = deps

  // ------------------------------------------------------------------
  // Build grid
  // ------------------------------------------------------------------

  const buildGrid = useCallback(async () => {
    if (!sessionId) return
    setLoading(true)
    setError(null)
    try {
      const params = new URLSearchParams()
      params.set('ipa_mode', ipaMode)
      params.set('syllable_mode', syllableMode)
      params.set('enhance', String(ocrEnhance))
      if (ocrMaxCols > 0) params.set('max_cols', String(ocrMaxCols))
      if (ocrMinConf > 0) params.set('min_conf', String(ocrMinConf))
      const res = await fetch(
        `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/build-grid?${params}`,
        { method: 'POST' },
      )
      if (!res.ok) {
        const data = await res.json().catch(() => ({}))
        throw new Error(data.detail || `HTTP ${res.status}`)
      }
      const data: StructuredGrid = await res.json()
      setGrid(data)
      setDirty(false)
      undoStack.current = []
      redoStack.current = []
    } catch (e) {
      setError(e instanceof Error ? e.message : String(e))
    } finally {
      setLoading(false)
    }
  }, [sessionId, ipaMode, syllableMode, ocrEnhance, ocrMaxCols, ocrMinConf, setGrid, setLoading, setError, setDirty, undoStack, redoStack])

  // ------------------------------------------------------------------
  // Re-run OCR with current quality settings, then rebuild grid
  // ------------------------------------------------------------------

  const rerunOcr = useCallback(async () => {
    if (!sessionId) return
    setLoading(true)
    setError(null)
    try {
      const params = new URLSearchParams()
      params.set('ipa_mode', ipaMode)
      params.set('syllable_mode', syllableMode)
      params.set('enhance', String(ocrEnhance))
      if (ocrMaxCols > 0) params.set('max_cols', String(ocrMaxCols))
      if (ocrMinConf > 0) params.set('min_conf', String(ocrMinConf))
      params.set('vision_fusion', String(visionFusion))
      if (documentCategory) params.set('doc_category', documentCategory)
      const res = await fetch(
        `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/rerun-ocr-and-build-grid?${params}`,
        { method: 'POST' },
      )
      if (!res.ok) {
        const data = await res.json().catch(() => ({}))
        throw new Error(data.detail || `HTTP ${res.status}`)
      }
      const data: StructuredGrid = await res.json()
      setGrid(data)
      setDirty(false)
      undoStack.current = []
      redoStack.current = []
    } catch (e) {
      setError(e instanceof Error ? e.message : String(e))
    } finally {
      setLoading(false)
    }
  }, [sessionId, ipaMode, syllableMode, ocrEnhance, ocrMaxCols, ocrMinConf, visionFusion, documentCategory, setGrid, setLoading, setError, setDirty, undoStack, redoStack])

  // ------------------------------------------------------------------
  // Load grid (with auto-build fallback on 404)
  // ------------------------------------------------------------------

  const loadGrid = useCallback(async () => {
    if (!sessionId) return
    setLoading(true)
    setError(null)
    try {
      const res = await fetch(
        `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/grid-editor`,
      )
      if (res.status === 404) {
        // No grid yet — build it with current modes
        const params = new URLSearchParams()
        params.set('ipa_mode', ipaMode)
        params.set('syllable_mode', syllableMode)
        params.set('enhance', String(ocrEnhance))
        if (ocrMaxCols > 0) params.set('max_cols', String(ocrMaxCols))
        if (ocrMinConf > 0) params.set('min_conf', String(ocrMinConf))
        const buildRes = await fetch(
          `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/build-grid?${params}`,
          { method: 'POST' },
        )
        if (buildRes.ok) {
          const data: StructuredGrid = await buildRes.json()
          setGrid(data)
          setDirty(false)
        }
        return
      }
      if (!res.ok) {
        const data = await res.json().catch(() => ({}))
        throw new Error(data.detail || `HTTP ${res.status}`)
      }
      const data: StructuredGrid = await res.json()
      setGrid(data)
      setDirty(false)
      undoStack.current = []
      redoStack.current = []
    } catch (e) {
      setError(e instanceof Error ? e.message : String(e))
    } finally {
      setLoading(false)
    }
    // Only depends on sessionId — mode changes are handled by the
    // separate useEffect below, not by re-triggering loadGrid.
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [sessionId])

  // ------------------------------------------------------------------
  // Auto-rebuild when IPA or syllable mode changes (skip initial mount)
  // ------------------------------------------------------------------

  const mountedRef = useRef(false)
  useEffect(() => {
    if (!mountedRef.current) {
      // Skip the first trigger (component mount) — don't rebuild yet
      mountedRef.current = true
      return
    }
    if (!sessionId) return
    const rebuild = async () => {
      setLoading(true)
      setError(null)
      try {
        const params = new URLSearchParams()
        params.set('ipa_mode', ipaMode)
        params.set('syllable_mode', syllableMode)
        const res = await fetch(
          `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/build-grid?${params}`,
          { method: 'POST' },
        )
        if (!res.ok) {
          const data = await res.json().catch(() => ({}))
          throw new Error(data.detail || `HTTP ${res.status}`)
        }
        const data: StructuredGrid = await res.json()
        setGrid(data)
        setDirty(false)
      } catch (e) {
        setError(e instanceof Error ? e.message : String(e))
      } finally {
        setLoading(false)
      }
    }
    rebuild()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [ipaMode, syllableMode])

  // ------------------------------------------------------------------
  // Save grid
  // ------------------------------------------------------------------

  const saveGrid = useCallback(async () => {
    if (!sessionId || !grid) return
    setSaving(true)
    try {
      const res = await fetch(
        `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/save-grid`,
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(grid),
        },
      )
      if (!res.ok) {
        const data = await res.json().catch(() => ({}))
        throw new Error(data.detail || `HTTP ${res.status}`)
      }
      setDirty(false)
    } catch (e) {
      setError(e instanceof Error ? e.message : String(e))
    } finally {
      setSaving(false)
    }
  }, [sessionId, grid, setSaving, setError, setDirty])

  return {
    buildGrid,
    rerunOcr,
    loadGrid,
    saveGrid,
  }
}
