import { useCallback, useRef, useState } from 'react'
import type { StructuredGrid } from './types'
import { MAX_UNDO } from './gridEditorTypes'
import type { IpaMode, SyllableMode } from './gridEditorTypes'
import { useGridEditorApi } from './useGridEditorApi'
import { useGridEditorActions } from './useGridEditorActions'
import { useGridEditorLayout } from './useGridEditorLayout'

// Re-export types so existing imports keep working
export type { GridEditorState, IpaMode, SyllableMode } from './gridEditorTypes'

export function useGridEditor(sessionId: string | null) {
  const [grid, setGrid] = useState<StructuredGrid | null>(null)
  const [loading, setLoading] = useState(false)
  const [saving, setSaving] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [dirty, setDirty] = useState(false)
  const [selectedCell, setSelectedCell] = useState<string | null>(null)
  const [selectedZone, setSelectedZone] = useState<number | null>(null)
  const [ipaMode, setIpaMode] = useState<IpaMode>('auto')
  const [syllableMode, setSyllableMode] = useState<SyllableMode>('auto')

  // OCR Quality Steps (A/B testing toggles — defaults off for now)
  const [ocrEnhance, setOcrEnhance] = useState(false)
  const [ocrMaxCols, setOcrMaxCols] = useState(0)
  const [ocrMinConf, setOcrMinConf] = useState(0)

  // Vision-LLM Fusion (Step 4)
  const [visionFusion, setVisionFusion] = useState(false)
  const [documentCategory, setDocumentCategory] = useState('vokabelseite')

  // Undo/redo stacks store serialized zone arrays
  const undoStack = useRef<string[]>([])
  const redoStack = useRef<string[]>([])

  const pushUndo = useCallback((zones: StructuredGrid['zones']) => {
    undoStack.current.push(JSON.stringify(zones))
    if (undoStack.current.length > MAX_UNDO) {
      undoStack.current.shift()
    }
    redoStack.current = []
  }, [])

  // ------------------------------------------------------------------
  // API calls (build, load, save, rerunOcr)
  // ------------------------------------------------------------------

  const { buildGrid, rerunOcr, loadGrid, saveGrid } = useGridEditorApi({
    sessionId,
    ipaMode,
    syllableMode,
    ocrEnhance,
    ocrMaxCols,
    ocrMinConf,
    visionFusion,
    documentCategory,
    setGrid,
    setLoading,
    setSaving,
    setError,
    setDirty,
    grid,
    undoStack,
    redoStack,
  })

  // ------------------------------------------------------------------
  // Cell editing, formatting, multi-select
  // ------------------------------------------------------------------

  const {
    updateCellText,
    setCellColor,
    toggleColumnBold,
    toggleRowHeader,
    autoCorrectColumnPatterns,
    selectedCells,
    toggleCellSelection,
    clearCellSelection,
    toggleSelectedBold,
  } = useGridEditorActions({ grid, setGrid, setDirty, pushUndo })

  // ------------------------------------------------------------------
  // Column/row management, layout dividers
  // ------------------------------------------------------------------

  const {
    deleteColumn,
    addColumn,
    deleteRow,
    addRow,
    commitUndoPoint,
    updateColumnDivider,
    updateLayoutHorizontals,
    splitColumnAt,
  } = useGridEditorLayout({ grid, setGrid, setDirty, pushUndo })

  // ------------------------------------------------------------------
  // Undo / Redo
  // ------------------------------------------------------------------

  const undo = useCallback(() => {
    if (!grid || undoStack.current.length === 0) return
    redoStack.current.push(JSON.stringify(grid.zones))
    const prev = undoStack.current.pop()!
    setGrid((g) => (g ? { ...g, zones: JSON.parse(prev) } : g))
    setDirty(true)
  }, [grid])

  const redo = useCallback(() => {
    if (!grid || redoStack.current.length === 0) return
    undoStack.current.push(JSON.stringify(grid.zones))
    const next = redoStack.current.pop()!
    setGrid((g) => (g ? { ...g, zones: JSON.parse(next) } : g))
    setDirty(true)
  }, [grid])

  const canUndo = undoStack.current.length > 0
  const canRedo = redoStack.current.length > 0

  // ------------------------------------------------------------------
  // Navigation helpers
  // ------------------------------------------------------------------

  const getAdjacentCell = useCallback(
    (cellId: string, direction: 'up' | 'down' | 'left' | 'right'): string | null => {
      if (!grid) return null
      for (const zone of grid.zones) {
        // Find the cell or derive row/col from cellId pattern
        const cell = zone.cells.find((c) => c.cell_id === cellId)
        let currentRow: number, currentCol: number
        if (cell) {
          currentRow = cell.row_index
          currentCol = cell.col_index
        } else {
          // Try to parse from cellId: Z{zone}_R{row}_C{col}
          const match = cellId.match(/^Z(\d+)_R(\d+)_C(\d+)$/)
          if (!match || parseInt(match[1]) !== zone.zone_index) continue
          currentRow = parseInt(match[2])
          currentCol = parseInt(match[3])
        }

        let targetRow = currentRow
        let targetCol = currentCol
        if (direction === 'up') targetRow--
        if (direction === 'down') targetRow++
        if (direction === 'left') targetCol--
        if (direction === 'right') targetCol++

        // Check bounds
        const hasRow = zone.rows.some((r) => r.index === targetRow)
        const hasCol = zone.columns.some((c) => c.index === targetCol)
        if (!hasRow || !hasCol) return null

        // Return existing cell ID or construct one
        const target = zone.cells.find(
          (c) => c.row_index === targetRow && c.col_index === targetCol,
        )
        return target?.cell_id ?? `Z${zone.zone_index}_R${String(targetRow).padStart(2, '0')}_C${targetCol}`
      }
      return null
    },
    [grid],
  )

  return {
    grid,
    loading,
    saving,
    error,
    dirty,
    selectedCell,
    selectedZone,
    selectedCells,
    setSelectedCell,
    setSelectedZone,
    buildGrid,
    loadGrid,
    saveGrid,
    updateCellText,
    toggleColumnBold,
    toggleRowHeader,
    undo,
    redo,
    canUndo,
    canRedo,
    getAdjacentCell,
    deleteColumn,
    addColumn,
    deleteRow,
    addRow,
    commitUndoPoint,
    updateColumnDivider,
    updateLayoutHorizontals,
    splitColumnAt,
    toggleCellSelection,
    clearCellSelection,
    toggleSelectedBold,
    autoCorrectColumnPatterns,
    setCellColor,
    ipaMode,
    setIpaMode,
    syllableMode,
    setSyllableMode,
    ocrEnhance,
    setOcrEnhance,
    ocrMaxCols,
    setOcrMaxCols,
    ocrMinConf,
    setOcrMinConf,
    visionFusion,
    setVisionFusion,
    documentCategory,
    setDocumentCategory,
    rerunOcr,
  }
}
