'use client'

/**
 * Custom hook encapsulating all state, data-fetching, CRUD operations,
 * and workflow actions for the Korrektur-Workspace page.
 */

import { useState, useEffect, useCallback, useMemo } from 'react'
import type {
  Klausur, StudentWork, Annotation, CriteriaScores,
  GradeInfo, AnnotationType, AnnotationPosition,
} from '../../../types'
import type { ExaminerWorkflow, ActiveTab, GradeTotals } from './workspace-types'
import { API_BASE } from './workspace-types'

/** Download a blob from url and trigger browser download with given filename. */
async function downloadBlob(url: string, filename: string) {
  const res = await fetch(url)
  if (!res.ok) throw new Error('Download failed')
  const blob = await res.blob()
  const blobUrl = window.URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = blobUrl; a.download = filename
  document.body.appendChild(a); a.click()
  document.body.removeChild(a); window.URL.revokeObjectURL(blobUrl)
}

export function useKorrekturWorkspace(
  klausurId: string,
  studentId: string,
  routerPush: (url: string) => void,
) {
  // ---- Core data state ----
  const [klausur, setKlausur] = useState<Klausur | null>(null)
  const [student, setStudent] = useState<StudentWork | null>(null)
  const [students, setStudents] = useState<StudentWork[]>([])
  const [annotations, setAnnotations] = useState<Annotation[]>([])
  const [gradeInfo, setGradeInfo] = useState<GradeInfo | null>(null)
  const [workflow, setWorkflow] = useState<ExaminerWorkflow | null>(null)

  // ---- UI flags ----
  const [loading, setLoading] = useState(true)
  const [saving, setSaving] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [activeTab, setActiveTab] = useState<ActiveTab>('kriterien')
  const [currentPage, setCurrentPage] = useState(1)
  const [totalPages] = useState(1)
  const [zoom, setZoom] = useState(100)
  const [documentUrl, setDocumentUrl] = useState<string | null>(null)
  const [generatingGutachten, setGeneratingGutachten] = useState(false)
  const [exporting, setExporting] = useState(false)

  // ---- Annotation state ----
  const [selectedTool, setSelectedTool] = useState<AnnotationType | null>(null)
  const [selectedAnnotation, setSelectedAnnotation] = useState<Annotation | null>(null)

  // ---- Form state ----
  const [criteriaScores, setCriteriaScores] = useState<CriteriaScores>({})
  const [gutachten, setGutachten] = useState('')

  // ---- Einigung state ----
  const [showEinigungModal, setShowEinigungModal] = useState(false)
  const [einigungGrade, setEinigungGrade] = useState<number>(0)
  const [einigungNotes, setEinigungNotes] = useState('')
  const [submittingWorkflow, setSubmittingWorkflow] = useState(false)

  // ---- Derived ----
  const currentIndex = students.findIndex(s => s.id === studentId)

  const annotationCounts = useMemo(() => {
    const counts: Record<AnnotationType, number> = {
      rechtschreibung: 0, grammatik: 0, inhalt: 0,
      struktur: 0, stil: 0, comment: 0, highlight: 0,
    }
    annotations.forEach((ann) => {
      counts[ann.type] = (counts[ann.type] || 0) + 1
    })
    return counts
  }, [annotations])

  // ---- Grade calculation ----
  const calculateTotalPoints = useCallback((): GradeTotals => {
    if (!gradeInfo?.criteria) return { raw: 0, weighted: 0, gradePoints: 0 }

    let totalWeighted = 0
    let totalWeight = 0

    Object.entries(gradeInfo.criteria).forEach(([key, criterion]) => {
      const score = criteriaScores[key] || 0
      totalWeighted += score * (criterion.weight / 100)
      totalWeight += criterion.weight
    })

    const percentage = totalWeight > 0 ? (totalWeighted / totalWeight) * 100 : 0

    let gradePoints = 0
    const thresholds = [
      { points: 15, min: 95 }, { points: 14, min: 90 }, { points: 13, min: 85 },
      { points: 12, min: 80 }, { points: 11, min: 75 }, { points: 10, min: 70 },
      { points: 9, min: 65 }, { points: 8, min: 60 }, { points: 7, min: 55 },
      { points: 6, min: 50 }, { points: 5, min: 45 }, { points: 4, min: 40 },
      { points: 3, min: 33 }, { points: 2, min: 27 }, { points: 1, min: 20 },
    ]
    for (const t of thresholds) {
      if (percentage >= t.min) { gradePoints = t.points; break }
    }

    return { raw: Math.round(totalWeighted), weighted: Math.round(percentage), gradePoints }
  }, [gradeInfo, criteriaScores])

  const totals = calculateTotalPoints()

  // ---- Data fetching ----
  const fetchData = useCallback(async () => {
    try {
      setLoading(true)

      const klausurRes = await fetch(`${API_BASE}/api/v1/klausuren/${klausurId}`)
      if (klausurRes.ok) setKlausur(await klausurRes.json())

      const studentsRes = await fetch(`${API_BASE}/api/v1/klausuren/${klausurId}/students`)
      if (studentsRes.ok) {
        const data = await studentsRes.json()
        setStudents(Array.isArray(data) ? data : data.students || [])
      }

      const studentRes = await fetch(`${API_BASE}/api/v1/students/${studentId}`)
      if (studentRes.ok) {
        const studentData = await studentRes.json()
        setStudent(studentData)
        setCriteriaScores(studentData.criteria_scores || {})
        setGutachten(studentData.gutachten || '')
      }

      const gradeInfoRes = await fetch(`${API_BASE}/api/v1/grade-info`)
      if (gradeInfoRes.ok) setGradeInfo(await gradeInfoRes.json())

      const workflowRes = await fetch(`${API_BASE}/api/v1/students/${studentId}/examiner-workflow`)
      if (workflowRes.ok) {
        const workflowData = await workflowRes.json()
        setWorkflow(workflowData)
        if (workflowData.workflow_status === 'einigung_required' && workflowData.first_result && workflowData.second_result) {
          const avgGrade = Math.round((workflowData.first_result.grade_points + workflowData.second_result.grade_points) / 2)
          setEinigungGrade(avgGrade)
        }
      }

      const annotationsEndpoint = workflow?.user_role === 'zk'
        ? `${API_BASE}/api/v1/students/${studentId}/annotations-filtered`
        : `${API_BASE}/api/v1/students/${studentId}/annotations`
      const annotationsRes = await fetch(annotationsEndpoint)
      if (annotationsRes.ok) {
        const annotationsData = await annotationsRes.json()
        setAnnotations(Array.isArray(annotationsData) ? annotationsData : annotationsData.annotations || [])
      }

      setDocumentUrl(`${API_BASE}/api/v1/students/${studentId}/file`)
      setError(null)
    } catch (err) {
      console.error('Failed to fetch data:', err)
      setError('Fehler beim Laden der Daten')
    } finally {
      setLoading(false)
    }
  }, [klausurId, studentId])

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

  // ---- Annotation CRUD ----
  const createAnnotation = useCallback(async (position: AnnotationPosition, type: AnnotationType) => {
    try {
      const newAnnotation = {
        page: currentPage, position, type, text: '',
        severity: type === 'rechtschreibung' || type === 'grammatik' ? 'minor' : 'major',
        role: 'first_examiner',
        linked_criterion: ['rechtschreibung', 'grammatik', 'inhalt', 'struktur', 'stil'].includes(type) ? type : undefined,
      }
      const res = await fetch(`${API_BASE}/api/v1/students/${studentId}/annotations`, {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(newAnnotation),
      })
      if (res.ok) {
        const created = await res.json()
        setAnnotations((prev) => [...prev, created])
        setSelectedAnnotation(created)
        setActiveTab('annotationen')
      } else {
        const errorData = await res.json()
        setError(errorData.detail || 'Fehler beim Erstellen der Annotation')
      }
    } catch (err) {
      console.error('Failed to create annotation:', err)
      setError('Fehler beim Erstellen der Annotation')
    }
  }, [studentId, currentPage])

  const updateAnnotation = useCallback(async (id: string, updates: Partial<Annotation>) => {
    try {
      const res = await fetch(`${API_BASE}/api/v1/annotations/${id}`, {
        method: 'PUT', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(updates),
      })
      if (res.ok) {
        const updated = await res.json()
        setAnnotations((prev) => prev.map((ann) => (ann.id === id ? updated : ann)))
        if (selectedAnnotation?.id === id) setSelectedAnnotation(updated)
      } else {
        const errorData = await res.json()
        setError(errorData.detail || 'Fehler beim Aktualisieren der Annotation')
      }
    } catch (err) {
      console.error('Failed to update annotation:', err)
      setError('Fehler beim Aktualisieren der Annotation')
    }
  }, [selectedAnnotation?.id])

  const deleteAnnotation = useCallback(async (id: string) => {
    try {
      const res = await fetch(`${API_BASE}/api/v1/annotations/${id}`, { method: 'DELETE' })
      if (res.ok) {
        setAnnotations((prev) => prev.filter((ann) => ann.id !== id))
        if (selectedAnnotation?.id === id) setSelectedAnnotation(null)
      } else {
        const errorData = await res.json()
        setError(errorData.detail || 'Fehler beim Loeschen der Annotation')
      }
    } catch (err) {
      console.error('Failed to delete annotation:', err)
      setError('Fehler beim Loeschen der Annotation')
    }
  }, [selectedAnnotation?.id])

  // ---- Criteria ----
  const saveCriteriaScores = useCallback(async (newScores: CriteriaScores) => {
    try {
      setSaving(true)
      const res = await fetch(`${API_BASE}/api/v1/students/${studentId}/criteria`, {
        method: 'PUT', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ criteria_scores: newScores }),
      })
      if (res.ok) { setStudent(await res.json()) }
      else { setError('Fehler beim Speichern') }
    } catch (err) {
      console.error('Failed to save criteria:', err)
      setError('Fehler beim Speichern')
    } finally { setSaving(false) }
  }, [studentId])

  const handleCriteriaChange = (criterion: string, value: number) => {
    const newScores = { ...criteriaScores, [criterion]: value }
    setCriteriaScores(newScores)
    saveCriteriaScores(newScores)
  }

  // ---- Gutachten ----
  const saveGutachten = useCallback(async () => {
    try {
      setSaving(true)
      const res = await fetch(`${API_BASE}/api/v1/students/${studentId}/gutachten`, {
        method: 'PUT', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ gutachten }),
      })
      if (res.ok) { setStudent(await res.json()) }
      else { setError('Fehler beim Speichern') }
    } catch (err) {
      console.error('Failed to save gutachten:', err)
      setError('Fehler beim Speichern')
    } finally { setSaving(false) }
  }, [studentId, gutachten])

  const generateGutachten = useCallback(async () => {
    try {
      setGeneratingGutachten(true)
      setError(null)
      const res = await fetch(`${API_BASE}/api/v1/students/${studentId}/gutachten/generate`, {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ criteria_scores: criteriaScores }),
      })
      if (res.ok) {
        const data = await res.json()
        const generatedText = [data.einleitung || '', '', data.hauptteil || '', '', data.fazit || '']
          .filter(Boolean).join('\n\n')
        setGutachten(generatedText)
        setActiveTab('gutachten')
      } else {
        const errorData = await res.json()
        setError(errorData.detail || 'Fehler bei der Gutachten-Generierung')
      }
    } catch (err) {
      console.error('Failed to generate gutachten:', err)
      setError('Fehler bei der Gutachten-Generierung')
    } finally { setGeneratingGutachten(false) }
  }, [studentId, criteriaScores])

  // ---- PDF Export ----
  const exportGutachtenPDF = useCallback(async () => {
    try {
      setExporting(true); setError(null)
      const name = student?.anonym_id?.replace(/\s+/g, '_') || 'Student'
      await downloadBlob(
        `${API_BASE}/api/v1/students/${studentId}/export/gutachten`,
        `Gutachten_${name}_${new Date().toISOString().split('T')[0]}.pdf`,
      )
    } catch (err) {
      console.error('Failed to export PDF:', err)
      setError('Fehler beim PDF-Export')
    } finally { setExporting(false) }
  }, [studentId, student?.anonym_id])

  const exportAnnotationsPDF = useCallback(async () => {
    try {
      setExporting(true); setError(null)
      const name = student?.anonym_id?.replace(/\s+/g, '_') || 'Student'
      await downloadBlob(
        `${API_BASE}/api/v1/students/${studentId}/export/annotations`,
        `Anmerkungen_${name}_${new Date().toISOString().split('T')[0]}.pdf`,
      )
    } catch (err) {
      console.error('Failed to export annotations PDF:', err)
      setError('Fehler beim PDF-Export')
    } finally { setExporting(false) }
  }, [studentId, student?.anonym_id])

  // ---- Workflow actions ----
  const submitErstkorrektur = useCallback(async () => {
    try {
      setSubmittingWorkflow(true)
      const assignRes = await fetch(`${API_BASE}/api/v1/students/${studentId}/examiner`, {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ examiner_id: 'current-user', examiner_role: 'first_examiner' }),
      })
      if (!assignRes.ok && assignRes.status !== 400) {
        const err = await assignRes.json()
        throw new Error(err.detail || 'Fehler bei der Zuweisung')
      }
      const submitRes = await fetch(`${API_BASE}/api/v1/students/${studentId}/examiner/result`, {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ grade_points: totals.gradePoints, notes: gutachten }),
      })
      if (submitRes.ok) { fetchData() }
      else {
        const err = await submitRes.json()
        setError(err.detail || 'Fehler beim Abschliessen der Erstkorrektur')
      }
    } catch (err) {
      console.error('Failed to submit Erstkorrektur:', err)
      setError('Fehler beim Abschliessen der Erstkorrektur')
    } finally { setSubmittingWorkflow(false) }
  }, [studentId, totals.gradePoints, gutachten, fetchData])

  const startZweitkorrektur = useCallback(async (zweitkorrektorId: string) => {
    try {
      setSubmittingWorkflow(true)
      const res = await fetch(`${API_BASE}/api/v1/students/${studentId}/start-zweitkorrektur`, {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ zweitkorrektor_id: zweitkorrektorId }),
      })
      if (res.ok) { fetchData() }
      else {
        const err = await res.json()
        setError(err.detail || 'Fehler beim Starten der Zweitkorrektur')
      }
    } catch (err) {
      console.error('Failed to start Zweitkorrektur:', err)
      setError('Fehler beim Starten der Zweitkorrektur')
    } finally { setSubmittingWorkflow(false) }
  }, [studentId, fetchData])

  const submitZweitkorrektur = useCallback(async () => {
    try {
      setSubmittingWorkflow(true)
      const res = await fetch(`${API_BASE}/api/v1/students/${studentId}/submit-zweitkorrektur`, {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          grade_points: totals.gradePoints, criteria_scores: criteriaScores,
          gutachten: gutachten ? { text: gutachten } : null, notes: '',
        }),
      })
      if (res.ok) {
        const result = await res.json()
        if (result.workflow_status === 'completed') {
          alert(`Auto-Konsens erreicht! Endnote: ${result.final_grade} Punkte`)
        } else if (result.workflow_status === 'einigung_required') {
          setShowEinigungModal(true)
        } else if (result.workflow_status === 'drittkorrektur_required') {
          alert(`Drittkorrektur erforderlich: Differenz ${result.grade_difference} Punkte`)
        }
        fetchData()
      } else {
        const err = await res.json()
        setError(err.detail || 'Fehler beim Abschliessen der Zweitkorrektur')
      }
    } catch (err) {
      console.error('Failed to submit Zweitkorrektur:', err)
      setError('Fehler beim Abschliessen der Zweitkorrektur')
    } finally { setSubmittingWorkflow(false) }
  }, [studentId, totals.gradePoints, criteriaScores, gutachten, fetchData])

  const submitEinigung = useCallback(async (type: 'agreed' | 'split' | 'escalated') => {
    try {
      setSubmittingWorkflow(true)
      const res = await fetch(`${API_BASE}/api/v1/students/${studentId}/einigung`, {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ final_grade: einigungGrade, einigung_notes: einigungNotes, einigung_type: type }),
      })
      if (res.ok) {
        const result = await res.json()
        setShowEinigungModal(false)
        if (result.workflow_status === 'drittkorrektur_required') {
          alert('Eskaliert zu Drittkorrektur')
        } else {
          alert(`Einigung abgeschlossen: Endnote ${result.final_grade} Punkte`)
        }
        fetchData()
      } else {
        const err = await res.json()
        setError(err.detail || 'Fehler bei der Einigung')
      }
    } catch (err) {
      console.error('Failed to submit Einigung:', err)
      setError('Fehler bei der Einigung')
    } finally { setSubmittingWorkflow(false) }
  }, [studentId, einigungGrade, einigungNotes, fetchData])

  // ---- Navigation ----
  const goToStudent = (direction: 'prev' | 'next') => {
    const newIndex = direction === 'prev' ? currentIndex - 1 : currentIndex + 1
    if (newIndex >= 0 && newIndex < students.length) {
      routerPush(`/education/klausur-korrektur/${klausurId}/${students[newIndex].id}`)
    }
  }

  return {
    // State
    klausur, student, students, annotations, gradeInfo, workflow,
    loading, saving, error, activeTab, currentPage, totalPages,
    zoom, documentUrl, generatingGutachten, exporting,
    selectedTool, selectedAnnotation,
    criteriaScores, gutachten,
    showEinigungModal, einigungGrade, einigungNotes, submittingWorkflow,
    currentIndex, annotationCounts, totals,

    // Actions
    setActiveTab, setCurrentPage, setZoom,
    setSelectedTool, setSelectedAnnotation,
    setGutachten, setError,
    setShowEinigungModal, setEinigungGrade, setEinigungNotes,
    createAnnotation, updateAnnotation, deleteAnnotation,
    handleCriteriaChange, saveGutachten, generateGutachten,
    exportGutachtenPDF, exportAnnotationsPDF,
    submitErstkorrektur, startZweitkorrektur, submitZweitkorrektur, submitEinigung,
    goToStudent,
  }
}
