'use client'

import React, { useEffect, useMemo, useRef, useState } from 'react'

type AgentInfo = {
  agent_id: string
  agent_version: string
  doc_type: string
  mc_count: number
}

type Finding = {
  check_id: string
  agent: string
  agent_version: string
  field_id?: string
  severity: 'HIGH' | 'MEDIUM' | 'LOW' | 'INFO'
  title: string
  norm?: string
  evidence?: string
  action?: string
  confidence?: number
  sources?: { source_type: string; source_id: string; detail?: string }[]
}

type Recommendation = {
  recommendation_id: string
  title: string
  body: string
  severity: string
  related_finding_ids: string[]
  estimated_effort_hours: number
}

type SlotOutput = {
  agent: string
  agent_version: string
  findings: Finding[]
  recommendations: Recommendation[]
  mc_total: number
  mc_ok: number
  mc_na: number
  mc_high: number
  mc_medium: number
  mc_low: number
  duration_ms: number
  confidence: number
  escalation_log: { stage: string; model: string; success: boolean; duration_ms: number }[]
}

type RunResult = {
  run_id: string
  agent_id: string
  finished: boolean
  results: Record<string, SlotOutput>
  vault_url: string
}

type StreamEvent = {
  type: string
  slot?: string
  [key: string]: any
}

const STORAGE_KEY = 'agent-test-state-v1'
const MAX_SLOTS = 5

export function AgentTestTab() {
  const [agents, setAgents] = useState<AgentInfo[]>([])
  const [agentId, setAgentId] = useState<string>('')
  const [urls, setUrls] = useState<string[]>(['', '', '', '', ''])
  const [running, setRunning] = useState(false)
  const [runId, setRunId] = useState<string>('')
  const [events, setEvents] = useState<StreamEvent[]>([])
  const [result, setResult] = useState<RunResult | null>(null)
  const [error, setError] = useState<string>('')
  const eventSrcRef = useRef<EventSource | null>(null)

  // Restore state from localStorage
  useEffect(() => {
    try {
      const s = localStorage.getItem(STORAGE_KEY)
      if (s) {
        const parsed = JSON.parse(s)
        if (parsed.agentId) setAgentId(parsed.agentId)
        if (Array.isArray(parsed.urls))
          setUrls(parsed.urls.slice(0, MAX_SLOTS).concat(
            new Array(MAX_SLOTS).fill('')).slice(0, MAX_SLOTS))
      }
    } catch { /* noop */ }
  }, [])
  useEffect(() => {
    try {
      localStorage.setItem(STORAGE_KEY,
        JSON.stringify({ agentId, urls }))
    } catch { /* quota */ }
  }, [agentId, urls])

  // Load agents
  useEffect(() => {
    fetch('/api/sdk/v1/specialist-agent/agents')
      .then(r => r.json())
      .then(d => {
        const list: AgentInfo[] = d.agents || []
        setAgents(list)
        if (list.length && !agentId) setAgentId(list[0].agent_id)
      })
      .catch(e => setError(`Agent-Liste fehlgeschlagen: ${e}`))
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  const startTest = async () => {
    setError('')
    setResult(null)
    setEvents([])
    const cleanUrls = urls.map(u => u.trim()).filter(Boolean)
    if (!agentId) { setError('Kein Agent ausgewählt.'); return }
    if (cleanUrls.length === 0) { setError('Mind. eine URL angeben.'); return }
    setRunning(true)
    try {
      const r = await fetch(
        '/api/sdk/v1/specialist-agent/test/start',
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            agent_id: agentId,
            urls: cleanUrls,
          }),
        },
      )
      if (!r.ok) {
        const j = await r.json().catch(() => ({}))
        throw new Error(j.error || `HTTP ${r.status}`)
      }
      const data = await r.json()
      setRunId(data.run_id)
      openStream(data.run_id)
      pollResult(data.run_id)
    } catch (e: any) {
      setError(e.message || String(e))
      setRunning(false)
    }
  }

  const openStream = (rid: string) => {
    try { eventSrcRef.current?.close() } catch { /* noop */ }
    const es = new EventSource(
      `/api/sdk/v1/specialist-agent/test/stream/${rid}`,
    )
    eventSrcRef.current = es
    es.onmessage = (ev) => {
      try {
        const data: StreamEvent = JSON.parse(ev.data)
        setEvents(prev => [...prev, data])
        if (data.type === 'stream_close' || data.type === 'run_complete') {
          try { es.close() } catch { /* noop */ }
        }
      } catch { /* noop */ }
    }
    es.onerror = () => { try { es.close() } catch { /* noop */ } }
  }

  const pollResult = async (rid: string) => {
    for (let i = 0; i < 360; i++) {
      try {
        const r = await fetch(
          `/api/sdk/v1/specialist-agent/run/${rid}/result`,
        )
        if (r.ok) {
          const d: RunResult = await r.json()
          if (d.finished) {
            setResult(d); setRunning(false); return
          }
        }
      } catch { /* noop */ }
      await new Promise(s => setTimeout(s, 2000))
    }
    setRunning(false)
  }

  const slotOutputs = useMemo(() => {
    if (!result) return []
    const items: { slot: string; output: SlotOutput }[] = []
    for (const slot of Object.keys(result.results)) {
      items.push({ slot, output: result.results[slot] })
    }
    return items.sort((a, b) => a.slot.localeCompare(b.slot))
  }, [result])

  const selectedAgent = agents.find(a => a.agent_id === agentId)

  return (
    <div className="space-y-4">
      <div className="rounded-lg border bg-white p-4 space-y-3">
        <h2 className="text-lg font-semibold">Agent-Test (max. {MAX_SLOTS} URLs)</h2>
        <p className="text-xs text-gray-500">
          Wählt einen Spezialisten-Agent und feuert ihn gegen 1-5 URLs gleichzeitig.
          Pro URL Speedometer + Findings + Empfehlungen mit Quellen-Herkunft (MC / Regex / LLM-Stufe).
          Keine Aussagen "rechtssicher" oder "garantiert" — alle solchen Wörter werden vor Ausgabe gelöscht.
        </p>
        <div className="flex flex-wrap gap-3 items-end">
          <div>
            <label className="block text-xs font-medium text-gray-600">Agent</label>
            <select value={agentId}
                    onChange={e => setAgentId(e.target.value)}
                    className="border rounded px-2 py-1 text-sm">
              {agents.map(a => (
                <option key={a.agent_id} value={a.agent_id}>
                  {a.agent_id} v{a.agent_version} ({a.mc_count} MCs)
                </option>
              ))}
            </select>
          </div>
          {selectedAgent && (
            <div className="text-xs text-gray-500">
              Doc-Type: <code>{selectedAgent.doc_type}</code>
            </div>
          )}
        </div>
        <div className="space-y-1">
          {urls.map((u, i) => (
            <div key={i} className="flex gap-2">
              <span className="text-xs font-mono text-gray-500 w-8 pt-1.5">URL{i+1}</span>
              <input value={u}
                     onChange={e => {
                       const next = [...urls]; next[i] = e.target.value
                       setUrls(next)
                     }}
                     placeholder="https://example.com/impressum"
                     className="flex-1 border rounded px-2 py-1 text-sm font-mono"/>
            </div>
          ))}
        </div>
        <div className="flex gap-2">
          <button onClick={startTest}
                  disabled={running}
                  className="bg-blue-600 hover:bg-blue-700 disabled:bg-gray-400 text-white text-sm px-4 py-2 rounded">
            {running ? 'Laufend...' : 'Test starten'}
          </button>
          {runId && (
            <span className="text-xs text-gray-500 self-center">
              Run-ID: <code>{runId}</code>
            </span>
          )}
        </div>
        {error && (
          <div className="bg-red-50 border-l-4 border-red-400 p-2 text-sm text-red-700">
            {error}
          </div>
        )}
      </div>

      {running && events.length > 0 && (
        <div className="rounded-lg border bg-gray-50 p-3 max-h-48 overflow-y-auto">
          <div className="text-xs font-mono space-y-1">
            {events.slice(-30).map((ev, i) => (
              <div key={i}>
                <span className="text-gray-400">[{ev.type}]</span>{' '}
                {ev.slot && <span className="text-blue-600">{ev.slot}</span>}{' '}
                {ev.severity && (
                  <span className={severityColor(ev.severity)}>
                    {ev.severity}
                  </span>
                )}{' '}
                {ev.title || ev.error || ev.label || ev.model || ev.url || ''}
              </div>
            ))}
          </div>
        </div>
      )}

      {slotOutputs.length > 0 && (
        <div className="space-y-3">
          {slotOutputs.map(({ slot, output }) => (
            <SlotCard key={slot} slot={slot} output={output} runId={runId}/>
          ))}
        </div>
      )}
    </div>
  )
}

function SlotCard({ slot, output, runId }: {
  slot: string
  output: SlotOutput
  runId: string
}) {
  const [showAll, setShowAll] = useState(false)
  const visibleFindings = showAll ? output.findings : output.findings.slice(0, 8)
  return (
    <div className="rounded-lg border bg-white p-4 space-y-3">
      <div className="flex items-baseline gap-3">
        <h3 className="font-semibold text-gray-800">Slot: {slot}</h3>
        <span className="text-xs text-gray-500">
          {output.duration_ms} ms · confidence {(output.confidence * 100).toFixed(0)}%
        </span>
        <a className="text-xs text-blue-600 hover:underline ml-auto"
           href={`/api/sdk/v1/specialist-agent/run/${runId}/artifacts`}
           target="_blank" rel="noreferrer">
          Artefakte ↗
        </a>
      </div>
      <Speedometer
        total={output.mc_total}
        ok={output.mc_ok}
        na={output.mc_na}
        high={output.mc_high}
        medium={output.mc_medium}
        low={output.mc_low}
      />
      {output.escalation_log.length > 0 && (
        <div className="text-xs text-gray-500">
          Eskalationen:{' '}
          {output.escalation_log.map((e, i) => (
            <span key={i} className="mr-2">
              {e.stage}/{e.model} {e.success ? '✓' : '✗'} ({e.duration_ms} ms)
            </span>
          ))}
        </div>
      )}
      {output.findings.length > 0 && (
        <div className="space-y-1">
          <div className="text-xs font-semibold uppercase text-gray-600">
            Findings ({output.findings.length})
          </div>
          {visibleFindings.map(f => (
            <FindingRow key={f.check_id} f={f}/>
          ))}
          {output.findings.length > 8 && (
            <button onClick={() => setShowAll(x => !x)}
                    className="text-xs text-blue-600 hover:underline">
              {showAll ? 'Weniger anzeigen' : `Alle ${output.findings.length} anzeigen`}
            </button>
          )}
        </div>
      )}
      {output.recommendations.length > 0 && (
        <div className="space-y-1">
          <div className="text-xs font-semibold uppercase text-gray-600">
            Empfehlungen ({output.recommendations.length}, gerollupt)
          </div>
          {output.recommendations.map(r => (
            <div key={r.recommendation_id}
                 className="border-l-2 border-emerald-400 bg-emerald-50 p-2 text-xs">
              <div className="font-semibold">{r.title}</div>
              <div className="text-gray-600">{r.body}</div>
              <div className="text-[10px] text-gray-500 mt-1">
                {r.related_finding_ids.length} Finding(s) · ~{r.estimated_effort_hours}h
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  )
}

function Speedometer({ total, ok, na, high, medium, low }: {
  total: number
  ok: number
  na: number
  high: number
  medium: number
  low: number
}) {
  const safeTotal = Math.max(total, 1)
  return (
    <div className="space-y-1">
      <div className="text-xs text-gray-500">{total} MCs geprüft</div>
      <div className="flex h-4 rounded overflow-hidden border">
        <Bar pct={(ok / safeTotal) * 100} color="#10b981"/>
        <Bar pct={(na / safeTotal) * 100} color="#94a3b8"/>
        <Bar pct={(high / safeTotal) * 100} color="#dc2626"/>
        <Bar pct={(medium / safeTotal) * 100} color="#f59e0b"/>
        <Bar pct={(low / safeTotal) * 100} color="#3b82f6"/>
      </div>
      <div className="flex flex-wrap gap-2 text-xs">
        <Legend color="#10b981" label={`OK ${ok}`}/>
        <Legend color="#94a3b8" label={`n/a ${na}`}/>
        <Legend color="#dc2626" label={`HIGH ${high}`}/>
        <Legend color="#f59e0b" label={`MEDIUM ${medium}`}/>
        <Legend color="#3b82f6" label={`LOW ${low}`}/>
      </div>
    </div>
  )
}

function Bar({ pct, color }: { pct: number; color: string }) {
  return <div style={{ width: `${pct}%`, background: color }}/>
}

function Legend({ color, label }: { color: string; label: string }) {
  return (
    <span className="inline-flex items-center gap-1">
      <span style={{ background: color }} className="w-2 h-2 inline-block rounded"/>
      <span>{label}</span>
    </span>
  )
}

function FindingRow({ f }: { f: Finding }) {
  const color = severityHex(f.severity)
  const sourceTags = (f.sources || [])
    .map(s => s.source_type)
    .filter((v, i, arr) => arr.indexOf(v) === i)
  return (
    <div className="p-2 border-l-2" style={{ borderColor: color }}>
      <div className="flex items-baseline gap-2 text-xs">
        <span style={{ color }} className="font-semibold">{f.severity}</span>
        <code className="text-gray-500">{f.check_id}</code>
        {sourceTags.map(t => (
          <span key={t} className="px-1 bg-gray-100 rounded text-[10px]">{t}</span>
        ))}
      </div>
      <div className="text-sm">{f.title}</div>
      {f.norm && <div className="text-[11px] text-gray-500">{f.norm}</div>}
      {f.evidence && (
        <div className="text-[11px] italic text-gray-600 mt-1">„{f.evidence}"</div>
      )}
      {f.action && (
        <div className="text-[11px] text-emerald-700 mt-1">
          → {f.action}
        </div>
      )}
    </div>
  )
}

function severityColor(sev: string) {
  return sev === 'HIGH' ? 'text-red-600 font-semibold' :
         sev === 'MEDIUM' ? 'text-amber-600 font-semibold' :
         sev === 'LOW' ? 'text-blue-600' : 'text-gray-600'
}

function severityHex(sev: string) {
  return sev === 'HIGH' ? '#dc2626' :
         sev === 'MEDIUM' ? '#f59e0b' :
         sev === 'LOW' ? '#3b82f6' : '#94a3b8'
}
