import { useCallback, useEffect, useMemo, useState } from 'react'
import { ActivityFeed } from './components/ActivityFeed'
import { AgentRoster } from './components/AgentRoster'
import { AgentTerminalGrid } from './components/AgentTerminalGrid'
import { ChatPanel } from './components/ChatPanel'
import { CommandDock } from './components/CommandDock'
import { GpuPanel } from './components/GpuPanel'
import { AmbientBackground } from './components/AmbientBackground'
import { LiveClusterMap } from './components/LiveClusterMap'
import { LiveDomainGrid } from './components/LiveDomainGrid'
import { ThemeToggle } from './components/ThemeToggle'
import type { Agent, AgentAnim, Approval, ChatMessage, FeedEntry, GpuStatus, StatusData, TerminalLine, WorkloadData } from './types'

const TABS = ['Overview', 'Terminals', 'Activity', 'Approvals', 'GPU'] as const
type Tab = (typeof TABS)[number]

function wsUrl() {
  const proto = window.location.protocol === 'https:' ? 'wss' : 'ws'
  return `${proto}://${window.location.host}/api/ws/ops`
}

function LiveClock() {
  const [now, setNow] = useState(new Date())
  useEffect(() => {
    const t = setInterval(() => setNow(new Date()), 1000)
    return () => clearInterval(t)
  }, [])
  return (
    <span className="text-xs font-mono text-[var(--text-faint)] hidden lg:inline tabular-nums">
      {now.toLocaleTimeString()}
    </span>
  )
}

export default function App() {
  const [tab, setTab] = useState<Tab>('Overview')
  const [agents, setAgents] = useState<Agent[]>([])
  const [status, setStatus] = useState<StatusData | null>(null)
  const [workload, setWorkload] = useState<WorkloadData | null>(null)
  const [gpu, setGpu] = useState<GpuStatus | null>(null)
  const [feed, setFeed] = useState<FeedEntry[]>([])
  const [approvals, setApprovals] = useState<Approval[]>([])
  const [chat, setChat] = useState<ChatMessage[]>([])
  const [anims, setAnims] = useState<Record<string, AgentAnim>>({})
  const [selectedId, setSelectedId] = useState<string | null>(null)
  const [busy, setBusy] = useState(false)
  const [terminals, setTerminals] = useState<Record<string, TerminalLine[]>>({})
  const [terminalLayout, setTerminalLayout] = useState<'grid' | 'focus'>('grid')

  const appendTerminal = useCallback((line: TerminalLine) => {
    setTerminals((prev) => {
      const cur = prev[line.agent_id] || []
      return { ...prev, [line.agent_id]: [...cur, line].slice(-300) }
    })
  }, [])

  const selectedAgent = useMemo(
    () => agents.find((a) => a.id === selectedId) || null,
    [agents, selectedId],
  )

  const load = useCallback(async () => {
    const [a, s, f, ap, g, t, w] = await Promise.all([
      fetch('/api/agents').then((r) => r.json()),
      fetch('/api/status').then((r) => r.json()),
      fetch('/api/feed').then((r) => r.json()),
      fetch('/api/approvals').then((r) => r.json()),
      fetch('/api/gpu').then((r) => r.json()).catch(() => null),
      fetch('/api/terminals').then((r) => r.json()).catch(() => ({ terminals: {} })),
      fetch('/api/workload').then((r) => r.json()).catch(() => null),
    ])
    setAgents(a.agents || [])
    setStatus(s)
    setGpu(g || s.gpu || null)
    setFeed(f.entries || [])
    setApprovals(ap.approvals || [])
    if (t.terminals) setTerminals(t.terminals)
    if (w?.zones) setWorkload(w)
  }, [])

  useEffect(() => {
    load()
    const ws = new WebSocket(wsUrl())
    ws.onmessage = (ev) => {
      const msg = JSON.parse(ev.data)
      if (msg.type === 'status') {
        setStatus(msg.data)
        if (msg.data.gpu) setGpu(msg.data.gpu)
      }
      if (msg.type === 'workload') setWorkload(msg.data)
      if (msg.type === 'terminal') appendTerminal(msg.line)
      if (msg.type === 'terminal_history' && msg.terminals) setTerminals(msg.terminals)
      if (msg.type === 'feed') setFeed((prev) => [msg.entry, ...prev].slice(0, 100))
      if (msg.type === 'agent_dispatch') {
        setSelectedId(msg.agent_id)
        setAnims((p) => ({ ...p, [msg.agent_id]: { agentId: msg.agent_id, state: 'walk', zone: msg.zone } }))
      }
      if (msg.type === 'agent_fetch') {
        setAnims((p) => ({ ...p, [msg.agent_id]: { agentId: msg.agent_id, state: 'fetch', zone: msg.zone } }))
      }
      if (msg.type === 'agent_return') {
        setAnims((p) => ({ ...p, [msg.agent_id]: { agentId: msg.agent_id, state: 'return', zone: msg.zone } }))
        setTimeout(() => {
          setAnims((p) => ({ ...p, [msg.agent_id]: { agentId: msg.agent_id, state: 'idle' } }))
        }, 1200)
      }
      if (msg.type === 'prompt_result') {
        setChat((c) => [...c, { role: 'agent', text: msg.answer, agent: msg.agent_id, ts: new Date().toISOString() }])
        setBusy(false)
        load()
      }
    }
    const iv = setInterval(load, 15000)
    return () => { ws.close(); clearInterval(iv) }
  }, [load, appendTerminal])

  const sendPrompt = async (message: string, agentId?: string) => {
    setBusy(true)
    setChat((c) => [...c, { role: 'user', text: message, ts: new Date().toISOString() }])
    if (agentId) setSelectedId(agentId)
    await fetch('/api/prompt', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ message, agent_id: agentId || undefined }),
    })
  }

  const decide = async (id: string, approved: boolean) => {
    await fetch(`/api/approvals/${id}/decide`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ approved }),
    })
    load()
  }

  const allOk = status && Object.values(status.domains).every((d) => d.level === 'ok')
  const totalTasks = agents.reduce((n, a) => n + (a.stats?.tasks || 0), 0)

  return (
    <div className="min-h-screen p-4 md:p-6 max-w-[96rem] mx-auto font-display flex flex-col gap-5 relative">
      <AmbientBackground />
      <header className="panel rounded-2xl px-5 py-4 flex flex-wrap justify-between items-center gap-4 relative overflow-hidden">
        <div className="header-aurora" />
        <div className="flex items-center gap-4 relative z-10">
          <div className="logo-mark">ATC</div>
          <div>
            <h1 className="text-2xl md:text-3xl font-bold tracking-tight neon-text" style={{ color: 'var(--accent)' }}>
              Command Center
            </h1>
            <p className="text-xs font-mono text-[var(--text-muted)]">
              {agents.length} agents · {totalTasks} missions · autonomous ops
            </p>
          </div>
        </div>
        <div className="flex items-center gap-3 flex-wrap relative z-10">
          <LiveClock />
          {status && (
            <span className={`status-pill ${allOk ? 'ok' : 'warn'}`}>
              {allOk ? 'All systems operational' : 'Attention required'}
            </span>
          )}
          {gpu?.ok && gpu.active_model && (
            <span className="status-pill gpu hidden md:inline-flex">
              GPU · {gpu.active_model}
            </span>
          )}
          <ThemeToggle />
        </div>
      </header>

      <AgentRoster
        agents={agents}
        animations={anims}
        selectedId={selectedId}
        onSelect={setSelectedId}
        onDelegate={(a) => setSelectedId(a.id)}
      />

      <section className="panel rounded-2xl p-5">
        <div className="flex flex-wrap items-end justify-between gap-3 mb-4">
          <div>
            <p className="section-eyebrow">Live agent shells</p>
            <h2 className="text-lg font-bold" style={{ color: 'var(--accent)' }}>Agent Terminals</h2>
            <p className="text-xs text-[var(--text-muted)] mt-1">Volg live hoe elke agent data ophaalt — HTTP probes, Dockhand, JMX, vLLM.</p>
          </div>
          <div className="flex gap-2">
            <button type="button" className={`tab-btn text-xs ${terminalLayout === 'grid' ? 'active' : ''}`} onClick={() => setTerminalLayout('grid')}>Grid</button>
            <button type="button" className={`tab-btn text-xs ${terminalLayout === 'focus' ? 'active' : ''}`} onClick={() => setTerminalLayout('focus')}>Focus</button>
          </div>
        </div>
        <AgentTerminalGrid
          agents={agents}
          terminals={terminals}
          animations={anims}
          selectedId={selectedId}
          onSelect={setSelectedId}
          layout={terminalLayout}
        />
      </section>

      <div className="grid grid-cols-1 xl:grid-cols-12 gap-5">
        <div className="xl:col-span-8 flex flex-col gap-5">
          <LiveClusterMap agents={agents} workload={workload} animations={anims} selectedId={selectedId} />

          <nav className="flex gap-2 flex-wrap">
            {TABS.map((t) => (
              <button key={t} type="button" onClick={() => setTab(t)} className={`tab-btn ${tab === t ? 'active' : ''}`}>
                {t}
                {t === 'Approvals' && approvals.length > 0 && (
                  <span className="tab-badge">{approvals.length}</span>
                )}
              </button>
            ))}
          </nav>

          <main className="panel rounded-2xl p-5 min-h-[280px]">
            {tab === 'Overview' && (
              <div>
                <p className="section-eyebrow mb-1">Infrastructure</p>
                <h3 className="text-lg font-bold mb-4" style={{ color: 'var(--text)' }}>Live Cluster Workload</h3>
                <LiveDomainGrid workload={workload} />
              </div>
            )}
            {tab === 'Terminals' && (
              <div>
                <p className="section-eyebrow mb-1">Mission trace</p>
                <h3 className="text-lg font-bold mb-4" style={{ color: 'var(--text)' }}>
                  {selectedAgent ? `${selectedAgent.name} — full terminal` : 'Select an agent'}
                </h3>
                {selectedAgent ? (
                  <AgentTerminalGrid
                    agents={agents}
                    terminals={terminals}
                    animations={anims}
                    selectedId={selectedId}
                    onSelect={setSelectedId}
                    layout="focus"
                  />
                ) : (
                  <p className="text-sm text-[var(--text-muted)]">Klik een agent in de roster of stuur een prompt.</p>
                )}
              </div>
            )}
            {tab === 'Activity' && (
              <div>
                <div className="flex items-center justify-between mb-4">
                  <div>
                    <p className="section-eyebrow">Event stream</p>
                    <h3 className="text-lg font-bold" style={{ color: 'var(--text)' }}>Agent Activity</h3>
                  </div>
                  {selectedAgent && (
                    <button type="button" className="btn-secondary text-xs" onClick={() => setSelectedId(null)}>
                      Clear filter
                    </button>
                  )}
                </div>
                <ActivityFeed feed={feed} agents={agents} filterAgentId={selectedId} />
              </div>
            )}
            {tab === 'Approvals' && (
              <div className="space-y-3">
                {approvals.length === 0 && <p className="text-[var(--text-muted)] text-sm">Geen pending approvals.</p>}
                {approvals.map((a) => {
                  const agent = agents.find((ag) => ag.id === a.agent_id)
                  return (
                    <div key={a.id} className="status-card rounded-xl p-4 flex gap-4" style={{ borderColor: 'var(--accent-secondary)' }}>
                      {agent && <span className="text-2xl">{agent.icon}</span>}
                      <div className="flex-1">
                        <div className="text-sm font-semibold" style={{ color: 'var(--accent-secondary)' }}>{a.action}</div>
                        <div className="text-xs text-[var(--text-muted)] mt-1">{a.reason}</div>
                        <div className="text-[10px] font-mono text-[var(--text-faint)] mt-1">via {agent?.name || a.agent_id}</div>
                        <div className="flex gap-2 mt-3">
                          <button type="button" onClick={() => decide(a.id, true)} className="btn-secondary text-[var(--status-ok)]">Approve</button>
                          <button type="button" onClick={() => decide(a.id, false)} className="btn-secondary text-[var(--status-down)]">Deny</button>
                        </div>
                      </div>
                    </div>
                  )
                })}
              </div>
            )}
            {tab === 'GPU' && <GpuPanel gpu={gpu} />}
          </main>
        </div>

        <div className="xl:col-span-4 flex flex-col gap-5">
          <GpuPanel gpu={gpu} compact />
          <ChatPanel messages={chat} agents={agents} selectedAgent={selectedAgent} busy={busy} />
        </div>
      </div>

      <CommandDock onSubmit={sendPrompt} busy={busy} selectedAgent={selectedAgent} />
    </div>
  )
}
