'use client'

import { useCallback, useEffect, useState, useRef } from 'react'
import { useSearchParams } from 'next/navigation'
import type { PipelineStep, DocumentCategory, SessionListItem } from './types'
import { KOMBI_V2_STEPS, dbStepToKombiV2Ui } from './types'

export type { SessionListItem }

const KLAUSUR_API = '/klausur-api'

/** Groups sessions by document_group_id for the session list */
export interface DocumentGroupView {
  group_id: string
  title: string
  sessions: SessionListItem[]
  page_count: number
}

function initSteps(): PipelineStep[] {
  return KOMBI_V2_STEPS.map((s, i) => ({
    ...s,
    status: i === 0 ? 'active' : 'pending',
  }))
}

export function useKombiPipeline() {
  const [currentStep, setCurrentStep] = useState(0)
  const [sessionId, setSessionId] = useState<string | null>(null)
  const [sessionName, setSessionName] = useState('')
  const [sessions, setSessions] = useState<SessionListItem[]>([])
  const [loadingSessions, setLoadingSessions] = useState(true)
  const [activeCategory, setActiveCategory] = useState<DocumentCategory | undefined>(undefined)
  const [isGroundTruth, setIsGroundTruth] = useState(false)
  const [pageNumber, setPageNumber] = useState<number | null>(null)
  const [steps, setSteps] = useState<PipelineStep[]>(initSteps())

  const searchParams = useSearchParams()
  const deepLinkHandled = useRef(false)
  const gridSaveRef = useRef<(() => Promise<void>) | null>(null)

  // ---- Session loading ----

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

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

  // ---- Group sessions by document_group_id ----

  const groupedSessions = useCallback((): (SessionListItem | DocumentGroupView)[] => {
    const groups = new Map<string, SessionListItem[]>()
    const ungrouped: SessionListItem[] = []

    for (const s of sessions) {
      if (s.document_group_id) {
        const existing = groups.get(s.document_group_id) || []
        existing.push(s)
        groups.set(s.document_group_id, existing)
      } else {
        ungrouped.push(s)
      }
    }

    const result: (SessionListItem | DocumentGroupView)[] = []

    // Sort groups by earliest created_at
    const sortedGroups = Array.from(groups.entries()).sort((a, b) => {
      const aTime = Math.min(...a[1].map(s => new Date(s.created_at).getTime()))
      const bTime = Math.min(...b[1].map(s => new Date(s.created_at).getTime()))
      return bTime - aTime
    })

    for (const [groupId, groupSessions] of sortedGroups) {
      groupSessions.sort((a, b) => (a.page_number || 0) - (b.page_number || 0))
      // Extract base title (remove " — S. X" suffix)
      const baseName = groupSessions[0]?.name?.replace(/ — S\. \d+$/, '') || 'Dokument'
      result.push({
        group_id: groupId,
        title: baseName,
        sessions: groupSessions,
        page_count: groupSessions.length,
      })
    }

    for (const s of ungrouped) {
      result.push(s)
    }

    // Sort by creation time (most recent first)
    const getTime = (item: SessionListItem | DocumentGroupView): number => {
      if ('group_id' in item) {
        return Math.min(...item.sessions.map((s: SessionListItem) => new Date(s.created_at).getTime()))
      }
      return new Date(item.created_at).getTime()
    }
    result.sort((a, b) => getTime(b) - getTime(a))

    return result
  }, [sessions])

  // ---- Open session ----

  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)
      setIsGroundTruth(!!data.ground_truth?.build_grid_reference)
      setPageNumber(data.grid_editor_result?.page_number?.number ?? null)

      // Determine UI step from DB state
      const dbStep = data.current_step || 1
      const hasGrid = !!data.grid_editor_result
      const hasStructure = !!data.structure_result
      const hasWords = !!data.word_result
      const hasGutterRepair = !!(data.ground_truth?.gutter_repair)

      let uiStep: number
      if (hasGrid && hasGutterRepair) {
        uiStep = 10 // gutter-repair (already analysed)
      } else if (hasGrid) {
        uiStep = 9 // grid-review
      } else if (hasStructure) {
        uiStep = 8 // grid-build
      } else if (hasWords) {
        uiStep = 7 // structure
      } else {
        uiStep = dbStepToKombiV2Ui(dbStep)
      }

      // Sessions only exist after upload, so always skip the upload step
      if (uiStep === 0) {
        uiStep = 1
      }

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

  // ---- Deep link handling ----

  useEffect(() => {
    if (deepLinkHandled.current) return
    const urlSession = searchParams.get('session')
    const urlStep = searchParams.get('step')
    if (urlSession) {
      deepLinkHandled.current = true
      openSession(urlSession).then(() => {
        if (urlStep) {
          const stepIdx = parseInt(urlStep, 10)
          if (!isNaN(stepIdx) && stepIdx >= 0 && stepIdx < KOMBI_V2_STEPS.length) {
            setCurrentStep(stepIdx)
          }
        }
      })
    }
  }, [searchParams, openSession])

  // ---- Step navigation ----

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

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

  const handleNext = useCallback(() => {
    if (currentStep >= steps.length - 1) {
      // Last step → return to session list
      setSteps(initSteps())
      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)
  }, [currentStep, steps, loadSessions])

  // ---- Session CRUD ----

  const handleNewSession = useCallback(() => {
    setSessionId(null)
    setSessionName('')
    setCurrentStep(0)
    setSteps(initSteps())
  }, [])

  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) handleNewSession()
    } catch (e) {
      console.error('Failed to delete session:', e)
    }
  }, [sessionId, handleNewSession])

  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)
    }
  }, [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)
    }
  }, [sessionId])

  return {
    // State
    currentStep,
    sessionId,
    sessionName,
    sessions,
    loadingSessions,
    activeCategory,
    isGroundTruth,
    pageNumber,
    steps,
    gridSaveRef,
    // Computed
    groupedSessions,
    // Actions
    loadSessions,
    openSession,
    goToStep,
    handleStepClick,
    handleNext,
    handleNewSession,
    deleteSession,
    renameSession,
    updateCategory,
    setSessionId,
    setSessionName,
    setIsGroundTruth,
  }
}
