'use client'

/**
 * Model Management Page
 *
 * Manage ML model backends (PyTorch vs ONNX), view status,
 * run benchmarks, and configure inference settings.
 */

import { useState, useEffect, useCallback } from 'react'
import { PagePurpose } from '@/components/common/PagePurpose'

const KLAUSUR_API = '/klausur-api'

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

type BackendMode = 'auto' | 'pytorch' | 'onnx'
type ModelStatus = 'available' | 'not_found' | 'loading' | 'error'
type Tab = 'overview' | 'benchmarks' | 'configuration'

interface ModelInfo {
  name: string
  key: string
  pytorch: { status: ModelStatus; size_mb: number; ram_mb: number }
  onnx: { status: ModelStatus; size_mb: number; ram_mb: number; quantized: boolean }
}

interface BenchmarkRow {
  model: string
  backend: string
  quantization: string
  size_mb: number
  ram_mb: number
  inference_ms: number
  load_time_s: number
}

interface StatusInfo {
  active_backend: BackendMode
  loaded_models: string[]
  cache_hits: number
  cache_misses: number
  uptime_s: number
}

// ---------------------------------------------------------------------------
// Mock data (used when backend is not available)
// ---------------------------------------------------------------------------

const MOCK_MODELS: ModelInfo[] = [
  {
    name: 'TrOCR Printed',
    key: 'trocr_printed',
    pytorch: { status: 'available', size_mb: 892, ram_mb: 1800 },
    onnx: { status: 'available', size_mb: 234, ram_mb: 620, quantized: true },
  },
  {
    name: 'TrOCR Handwritten',
    key: 'trocr_handwritten',
    pytorch: { status: 'available', size_mb: 892, ram_mb: 1800 },
    onnx: { status: 'not_found', size_mb: 0, ram_mb: 0, quantized: false },
  },
  {
    name: 'PP-DocLayout',
    key: 'pp_doclayout',
    pytorch: { status: 'not_found', size_mb: 0, ram_mb: 0 },
    onnx: { status: 'available', size_mb: 48, ram_mb: 180, quantized: false },
  },
]

const MOCK_BENCHMARKS: BenchmarkRow[] = [
  { model: 'TrOCR Printed', backend: 'PyTorch', quantization: 'FP32', size_mb: 892, ram_mb: 1800, inference_ms: 142, load_time_s: 3.2 },
  { model: 'TrOCR Printed', backend: 'ONNX', quantization: 'INT8', size_mb: 234, ram_mb: 620, inference_ms: 38, load_time_s: 0.8 },
  { model: 'TrOCR Handwritten', backend: 'PyTorch', quantization: 'FP32', size_mb: 892, ram_mb: 1800, inference_ms: 156, load_time_s: 3.4 },
  { model: 'PP-DocLayout', backend: 'ONNX', quantization: 'FP32', size_mb: 48, ram_mb: 180, inference_ms: 22, load_time_s: 0.3 },
]

const MOCK_STATUS: StatusInfo = {
  active_backend: 'auto',
  loaded_models: ['trocr_printed (ONNX)', 'pp_doclayout (ONNX)'],
  cache_hits: 1247,
  cache_misses: 83,
  uptime_s: 86400,
}

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function StatusBadge({ status }: { status: ModelStatus }) {
  const cls =
    status === 'available'
      ? 'bg-emerald-100 text-emerald-800 border-emerald-200'
      : status === 'loading'
        ? 'bg-blue-100 text-blue-800 border-blue-200'
        : status === 'not_found'
          ? 'bg-slate-100 text-slate-500 border-slate-200'
          : 'bg-red-100 text-red-800 border-red-200'
  const label =
    status === 'available' ? 'Verfuegbar'
      : status === 'loading' ? 'Laden...'
        : status === 'not_found' ? 'Nicht vorhanden'
          : 'Fehler'
  return (
    <span className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium border ${cls}`}>
      {label}
    </span>
  )
}

function formatBytes(mb: number) {
  if (mb === 0) return '--'
  if (mb >= 1000) return `${(mb / 1000).toFixed(1)} GB`
  return `${mb} MB`
}

function formatUptime(seconds: number) {
  const h = Math.floor(seconds / 3600)
  const m = Math.floor((seconds % 3600) / 60)
  if (h > 0) return `${h}h ${m}m`
  return `${m}m`
}

// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------

export default function ModelManagementPage() {
  const [tab, setTab] = useState<Tab>('overview')
  const [models, setModels] = useState<ModelInfo[]>(MOCK_MODELS)
  const [benchmarks, setBenchmarks] = useState<BenchmarkRow[]>(MOCK_BENCHMARKS)
  const [status, setStatus] = useState<StatusInfo>(MOCK_STATUS)
  const [backend, setBackend] = useState<BackendMode>('auto')
  const [saving, setSaving] = useState(false)
  const [benchmarkRunning, setBenchmarkRunning] = useState(false)
  const [usingMock, setUsingMock] = useState(false)

  // Load status
  const loadStatus = useCallback(async () => {
    try {
      const res = await fetch(`${KLAUSUR_API}/api/v1/models/status`)
      if (res.ok) {
        const data = await res.json()
        setStatus(data)
        setBackend(data.active_backend || 'auto')
        setUsingMock(false)
      } else {
        setUsingMock(true)
      }
    } catch {
      setUsingMock(true)
    }
  }, [])

  // Load models
  const loadModels = useCallback(async () => {
    try {
      const res = await fetch(`${KLAUSUR_API}/api/v1/models`)
      if (res.ok) {
        const data = await res.json()
        if (data.models?.length) setModels(data.models)
      }
    } catch {
      // Keep mock data
    }
  }, [])

  // Load benchmarks
  const loadBenchmarks = useCallback(async () => {
    try {
      const res = await fetch(`${KLAUSUR_API}/api/v1/models/benchmarks`)
      if (res.ok) {
        const data = await res.json()
        if (data.benchmarks?.length) setBenchmarks(data.benchmarks)
      }
    } catch {
      // Keep mock data
    }
  }, [])

  useEffect(() => {
    loadStatus()
    loadModels()
    loadBenchmarks()
  }, [loadStatus, loadModels, loadBenchmarks])

  // Save backend preference
  const saveBackend = async (mode: BackendMode) => {
    setBackend(mode)
    setSaving(true)
    try {
      await fetch(`${KLAUSUR_API}/api/v1/models/backend`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ backend: mode }),
      })
      await loadStatus()
    } catch {
      // Silently handle — mock mode
    } finally {
      setSaving(false)
    }
  }

  // Run benchmark
  const runBenchmark = async () => {
    setBenchmarkRunning(true)
    try {
      const res = await fetch(`${KLAUSUR_API}/api/v1/models/benchmark`, {
        method: 'POST',
      })
      if (res.ok) {
        const data = await res.json()
        if (data.benchmarks?.length) setBenchmarks(data.benchmarks)
      }
      await loadBenchmarks()
    } catch {
      // Keep existing data
    } finally {
      setBenchmarkRunning(false)
    }
  }

  const tabs: { key: Tab; label: string }[] = [
    { key: 'overview', label: 'Uebersicht' },
    { key: 'benchmarks', label: 'Benchmarks' },
    { key: 'configuration', label: 'Konfiguration' },
  ]

  return (
    <div className="space-y-6">
      <div className="max-w-7xl mx-auto p-6 space-y-6">
        <PagePurpose
          title="Model Management"
          purpose="Verwaltung der ML-Modelle fuer OCR und Layout-Erkennung. Vergleich von PyTorch- und ONNX-Backends, Benchmark-Tests und Backend-Konfiguration."
          audience={['Entwickler', 'DevOps']}
          defaultCollapsed
          architecture={{
            services: ['klausur-service (FastAPI, Port 8086)'],
            databases: ['Dateisystem (Modell-Dateien)'],
          }}
          relatedPages={[
            { name: 'OCR Pipeline', href: '/ai/ocr-pipeline', description: 'OCR-Pipeline ausfuehren' },
            { name: 'OCR Vergleich', href: '/ai/ocr-compare', description: 'OCR-Methoden vergleichen' },
            { name: 'GPU Infrastruktur', href: '/ai/gpu', description: 'GPU-Ressourcen verwalten' },
          ]}
        />

        {/* Header */}
        <div className="flex items-center justify-between">
          <div>
            <h1 className="text-2xl font-bold text-slate-900">Model Management</h1>
            <p className="text-sm text-slate-500 mt-1">
              {models.length} Modelle konfiguriert
              {usingMock && (
                <span className="ml-2 text-xs bg-amber-100 text-amber-700 px-1.5 py-0.5 rounded">
                  Mock-Daten (Backend nicht erreichbar)
                </span>
              )}
            </p>
          </div>
        </div>

        {/* Status Cards */}
        <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
          <div className="bg-white rounded-lg border border-slate-200 px-4 py-3">
            <p className="text-xs text-slate-500 uppercase font-medium">Aktives Backend</p>
            <p className="text-lg font-semibold text-slate-900 mt-1">{status.active_backend.toUpperCase()}</p>
          </div>
          <div className="bg-white rounded-lg border border-slate-200 px-4 py-3">
            <p className="text-xs text-slate-500 uppercase font-medium">Geladene Modelle</p>
            <p className="text-lg font-semibold text-slate-900 mt-1">{status.loaded_models.length}</p>
          </div>
          <div className="bg-white rounded-lg border border-slate-200 px-4 py-3">
            <p className="text-xs text-slate-500 uppercase font-medium">Cache Hit-Rate</p>
            <p className="text-lg font-semibold text-slate-900 mt-1">
              {status.cache_hits + status.cache_misses > 0
                ? `${((status.cache_hits / (status.cache_hits + status.cache_misses)) * 100).toFixed(1)}%`
                : '--'}
            </p>
          </div>
          <div className="bg-white rounded-lg border border-slate-200 px-4 py-3">
            <p className="text-xs text-slate-500 uppercase font-medium">Uptime</p>
            <p className="text-lg font-semibold text-slate-900 mt-1">{formatUptime(status.uptime_s)}</p>
          </div>
        </div>

        {/* Tabs */}
        <div className="border-b border-slate-200">
          <nav className="flex gap-4">
            {tabs.map(t => (
              <button
                key={t.key}
                onClick={() => setTab(t.key)}
                className={`pb-3 px-1 text-sm font-medium border-b-2 transition-colors ${
                  tab === t.key
                    ? 'border-teal-500 text-teal-600'
                    : 'border-transparent text-slate-500 hover:text-slate-700'
                }`}
              >
                {t.label}
              </button>
            ))}
          </nav>
        </div>

        {/* Overview Tab */}
        {tab === 'overview' && (
          <div className="space-y-4">
            <h3 className="text-sm font-medium text-slate-700">Verfuegbare Modelle</h3>
            <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
              {models.map(m => (
                <div key={m.key} className="bg-white rounded-lg border border-slate-200 overflow-hidden">
                  <div className="px-4 py-3 border-b border-slate-100">
                    <h4 className="font-semibold text-slate-900">{m.name}</h4>
                    <p className="text-xs text-slate-400 mt-0.5 font-mono">{m.key}</p>
                  </div>
                  <div className="px-4 py-3 space-y-3">
                    {/* PyTorch */}
                    <div className="flex items-center justify-between">
                      <div className="flex items-center gap-2">
                        <span className="text-xs font-medium text-slate-600 w-16">PyTorch</span>
                        <StatusBadge status={m.pytorch.status} />
                      </div>
                      {m.pytorch.status === 'available' && (
                        <span className="text-xs text-slate-400">
                          {formatBytes(m.pytorch.size_mb)} / {formatBytes(m.pytorch.ram_mb)} RAM
                        </span>
                      )}
                    </div>
                    {/* ONNX */}
                    <div className="flex items-center justify-between">
                      <div className="flex items-center gap-2">
                        <span className="text-xs font-medium text-slate-600 w-16">ONNX</span>
                        <StatusBadge status={m.onnx.status} />
                      </div>
                      {m.onnx.status === 'available' && (
                        <span className="text-xs text-slate-400">
                          {formatBytes(m.onnx.size_mb)} / {formatBytes(m.onnx.ram_mb)} RAM
                          {m.onnx.quantized && (
                            <span className="ml-1 text-xs bg-violet-100 text-violet-700 px-1 rounded">INT8</span>
                          )}
                        </span>
                      )}
                    </div>
                  </div>
                </div>
              ))}
            </div>

            {/* Loaded Models List */}
            {status.loaded_models.length > 0 && (
              <div>
                <h3 className="text-sm font-medium text-slate-700 mb-2">Aktuell geladen</h3>
                <div className="flex flex-wrap gap-2">
                  {status.loaded_models.map((m, i) => (
                    <span key={i} className="inline-flex items-center px-3 py-1 rounded-full text-sm bg-teal-50 text-teal-700 border border-teal-200">
                      {m}
                    </span>
                  ))}
                </div>
              </div>
            )}
          </div>
        )}

        {/* Benchmarks Tab */}
        {tab === 'benchmarks' && (
          <div className="space-y-4">
            <div className="flex items-center justify-between">
              <h3 className="text-sm font-medium text-slate-700">PyTorch vs ONNX Vergleich</h3>
              <button
                onClick={runBenchmark}
                disabled={benchmarkRunning}
                className="inline-flex items-center gap-2 px-4 py-2 bg-teal-600 text-white rounded-lg hover:bg-teal-700 disabled:opacity-50 disabled:cursor-not-allowed text-sm font-medium transition-colors"
              >
                {benchmarkRunning ? (
                  <>
                    <svg className="animate-spin h-4 w-4" fill="none" viewBox="0 0 24 24">
                      <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
                      <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
                    </svg>
                    Benchmark laeuft...
                  </>
                ) : (
                  'Benchmark starten'
                )}
              </button>
            </div>

            <div className="bg-white rounded-lg border border-slate-200 overflow-hidden">
              <div className="overflow-x-auto">
                <table className="w-full text-sm">
                  <thead>
                    <tr className="border-b border-slate-200 bg-slate-50 text-left text-slate-500">
                      <th className="px-4 py-3 font-medium">Modell</th>
                      <th className="px-4 py-3 font-medium">Backend</th>
                      <th className="px-4 py-3 font-medium">Quantisierung</th>
                      <th className="px-4 py-3 font-medium text-right">Groesse</th>
                      <th className="px-4 py-3 font-medium text-right">RAM</th>
                      <th className="px-4 py-3 font-medium text-right">Inferenz</th>
                      <th className="px-4 py-3 font-medium text-right">Ladezeit</th>
                    </tr>
                  </thead>
                  <tbody>
                    {benchmarks.map((b, i) => (
                      <tr key={i} className="border-b border-slate-100 hover:bg-slate-50">
                        <td className="px-4 py-3 font-medium text-slate-900">{b.model}</td>
                        <td className="px-4 py-3">
                          <span className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ${
                            b.backend === 'ONNX'
                              ? 'bg-violet-100 text-violet-700'
                              : 'bg-orange-100 text-orange-700'
                          }`}>
                            {b.backend}
                          </span>
                        </td>
                        <td className="px-4 py-3 text-slate-600">{b.quantization}</td>
                        <td className="px-4 py-3 text-right text-slate-600">{formatBytes(b.size_mb)}</td>
                        <td className="px-4 py-3 text-right text-slate-600">{formatBytes(b.ram_mb)}</td>
                        <td className="px-4 py-3 text-right">
                          <span className={`font-mono ${b.inference_ms < 50 ? 'text-emerald-600' : b.inference_ms < 100 ? 'text-amber-600' : 'text-red-600'}`}>
                            {b.inference_ms} ms
                          </span>
                        </td>
                        <td className="px-4 py-3 text-right text-slate-500">{b.load_time_s.toFixed(1)}s</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </div>

            {benchmarks.length === 0 && (
              <div className="text-center py-12 text-slate-400">
                <p className="text-lg">Keine Benchmark-Daten</p>
                <p className="text-sm mt-1">Klicken Sie &quot;Benchmark starten&quot; um einen Vergleich durchzufuehren.</p>
              </div>
            )}
          </div>
        )}

        {/* Configuration Tab */}
        {tab === 'configuration' && (
          <div className="space-y-6">
            {/* Backend Selector */}
            <div className="bg-white rounded-lg border border-slate-200 p-5">
              <h3 className="text-sm font-semibold text-slate-900 mb-1">Inference Backend</h3>
              <p className="text-sm text-slate-500 mb-4">
                Waehlen Sie welches Backend fuer die Modell-Inferenz verwendet werden soll.
              </p>
              <div className="space-y-3">
                {([
                  {
                    mode: 'auto' as const,
                    label: 'Auto',
                    desc: 'ONNX wenn verfuegbar, Fallback auf PyTorch.',
                  },
                  {
                    mode: 'pytorch' as const,
                    label: 'PyTorch',
                    desc: 'Immer PyTorch verwenden. Hoeherer RAM-Verbrauch, volle Flexibilitaet.',
                  },
                  {
                    mode: 'onnx' as const,
                    label: 'ONNX',
                    desc: 'Immer ONNX verwenden. Schneller und weniger RAM, Fehler wenn nicht vorhanden.',
                  },
                ] as const).map(opt => (
                  <label
                    key={opt.mode}
                    className={`flex items-start gap-3 p-3 rounded-lg border cursor-pointer transition-colors ${
                      backend === opt.mode
                        ? 'border-teal-300 bg-teal-50'
                        : 'border-slate-200 hover:bg-slate-50'
                    }`}
                  >
                    <input
                      type="radio"
                      name="backend"
                      value={opt.mode}
                      checked={backend === opt.mode}
                      onChange={() => saveBackend(opt.mode)}
                      disabled={saving}
                      className="mt-1 text-teal-600 focus:ring-teal-500"
                    />
                    <div>
                      <span className="font-medium text-slate-900">{opt.label}</span>
                      <p className="text-sm text-slate-500 mt-0.5">{opt.desc}</p>
                    </div>
                  </label>
                ))}
              </div>
              {saving && (
                <p className="text-xs text-teal-600 mt-3">Speichere...</p>
              )}
            </div>

            {/* Model Details Table */}
            <div className="bg-white rounded-lg border border-slate-200 p-5">
              <h3 className="text-sm font-semibold text-slate-900 mb-4">Modell-Details</h3>
              <div className="overflow-x-auto">
                <table className="w-full text-sm">
                  <thead>
                    <tr className="border-b border-slate-200 text-left text-slate-500">
                      <th className="pb-2 font-medium">Modell</th>
                      <th className="pb-2 font-medium">PyTorch</th>
                      <th className="pb-2 font-medium text-right">Groesse (PT)</th>
                      <th className="pb-2 font-medium">ONNX</th>
                      <th className="pb-2 font-medium text-right">Groesse (ONNX)</th>
                      <th className="pb-2 font-medium text-right">Einsparung</th>
                    </tr>
                  </thead>
                  <tbody>
                    {models.map(m => {
                      const ptAvail = m.pytorch.status === 'available'
                      const oxAvail = m.onnx.status === 'available'
                      const savings = ptAvail && oxAvail && m.pytorch.size_mb > 0
                        ? Math.round((1 - m.onnx.size_mb / m.pytorch.size_mb) * 100)
                        : null
                      return (
                        <tr key={m.key} className="border-b border-slate-100">
                          <td className="py-2.5 font-medium text-slate-900">{m.name}</td>
                          <td className="py-2.5"><StatusBadge status={m.pytorch.status} /></td>
                          <td className="py-2.5 text-right text-slate-500">{ptAvail ? formatBytes(m.pytorch.size_mb) : '--'}</td>
                          <td className="py-2.5"><StatusBadge status={m.onnx.status} /></td>
                          <td className="py-2.5 text-right text-slate-500">{oxAvail ? formatBytes(m.onnx.size_mb) : '--'}</td>
                          <td className="py-2.5 text-right">
                            {savings !== null ? (
                              <span className="text-emerald-600 font-medium">-{savings}%</span>
                            ) : (
                              <span className="text-slate-300">--</span>
                            )}
                          </td>
                        </tr>
                      )
                    })}
                  </tbody>
                </table>
              </div>
            </div>
          </div>
        )}
      </div>
    </div>
  )
}
