import { useEffect, useState } from 'react'
import api from '../api/client'
import StatusBadge from './StatusBadge'
import { copyToClipboard } from '../utils/clipboard'
import { useSettingsStore } from '../stores/settings'
import TerminalModal from './TerminalModal'
import ScriptModal from './ScriptModal'
import {
  X, Cpu, MemoryStick, HardDrive, Clock, Network, Shield, Route,
  Globe, Key, Download, Terminal, Wifi, Search, Plus, Trash2, Copy, Check, ExternalLink, Unplug, Plug, MonitorSmartphone, Ban,
  FileKey, UserCheck, Database, CalendarClock, Cable, Settings, Server, GitBranch, Play, Power, ChevronDown, ChevronRight, Pencil, FileCode,
} from 'lucide-react'

// Two-level navigation structure (DATAZONE style)
const mainCategories = [
  { id: 'uebersicht', label: 'Uebersicht' },
  { id: 'netzwerk', label: 'Netzwerk' },
  { id: 'sicherheit', label: 'Sicherheit' },
  { id: 'daten', label: 'Daten' },
  { id: 'system', label: 'System' },
]

const subItems = {
  netzwerk: [
    { id: 'interfaces', label: 'Interfaces', icon: Network },
    { id: 'vpn', label: 'VPN (WireGuard)', icon: Shield, platforms: ['freebsd'] },
    { id: 'routes', label: 'Routen', icon: GitBranch },
    { id: 'dhcp', label: 'DHCP', icon: Server, platforms: ['freebsd'] },
    { id: 'gateways', label: 'Gateways', icon: Globe },
  ],
  sicherheit: [
    { id: 'certs', label: 'Zertifikate', icon: FileKey, platforms: ['freebsd'] },
    { id: 'security', label: 'Logins', icon: UserCheck, platforms: ['freebsd'] },
  ],
  daten: [
    { id: 'backups', label: 'Backups', icon: Database },
    { id: 'tasks', label: 'Aufgaben', icon: CalendarClock, platforms: ['freebsd', 'linux'] },
    { id: 'tunnels', label: 'Tunnel', icon: Cable },
  ],
  system: [
    { id: 'services', label: 'Dienste', icon: Settings },
    { id: 'updates', label: 'Updates', icon: Download, platforms: ['freebsd', 'linux'] },
    { id: 'agent', label: 'Agent', icon: Cpu },
  ],
}

export default function AgentPanel({ agentId, customers, onClose, onReload }) {
  const [data, setData] = useState(null)
  const [mainTab, setMainTab] = useState('uebersicht')
  const [subTab, setSubTab] = useState('overview')
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    setLoading(true)
    setMainTab('uebersicht')
    setSubTab('overview')
    api.getAgent(agentId).then(setData).finally(() => setLoading(false))
  }, [agentId])

  useEffect(() => {
    if (!data) return
    const iv = setInterval(() => {
      api.getAgent(agentId).then(setData)
    }, 30000)
    return () => clearInterval(iv)
  }, [agentId, data])

  if (loading) return <Panel onClose={onClose}><div className="p-6 text-gray-500">Laden...</div></Panel>
  if (!data) return <Panel onClose={onClose}><div className="p-6 text-red-400">Nicht gefunden</div></Panel>

  const { agent, system_data: sys, status } = data
  const cust = agent.customer_id ? customers.find((c) => c.id === agent.customer_id) : null
  const platform = agent.platform || 'freebsd'

  // Filter sub-items by platform and determine visible main categories
  const getVisibleSubs = (catId) => {
    const items = subItems[catId] || []
    let filtered = items.filter(s => !s.platforms || s.platforms.includes(platform))
    // Dynamic sub-tabs based on data availability
    if (catId === 'netzwerk') {
      if (sys?.haproxy) {
        filtered = [...filtered, { id: 'haproxy', label: 'HAProxy', icon: Server }]
      }
      if (sys?.caddy) {
        filtered = [...filtered, { id: 'caddy', label: 'Caddy', icon: Globe }]
      }
    }
    return filtered
  }

  const visibleMainTabs = mainCategories.filter(cat => {
    if (cat.id === 'uebersicht') return true
    return getVisibleSubs(cat.id).length > 0
  })

  const handleMainTabChange = (catId) => {
    setMainTab(catId)
    if (catId === 'uebersicht') {
      setSubTab('overview')
    } else {
      const subs = getVisibleSubs(catId)
      if (subs.length > 0) setSubTab(subs[0].id)
    }
  }

  // For "gateways" sub-tab, we render the OverviewTab's gateway section standalone
  const currentSubs = mainTab !== 'uebersicht' ? getVisibleSubs(mainTab) : []

  const renderContent = () => {
    if (!sys) return <div className="text-gray-500">Keine Systemdaten</div>
    const tab = subTab
    if (tab === 'overview') return <OverviewTab sys={sys} agentId={agentId} />
    if (tab === 'interfaces') return <InterfacesTab sys={sys} agentId={agentId} />
    if (tab === 'services') return <ServicesTab sys={sys} />
    if (tab === 'tunnels') return <TunnelTab agentId={agentId} agent={agent} />
    if (tab === 'vpn') return <><VPNTab sys={sys} /><div className="mt-6"><WireGuardTab agentId={agentId} sys={sys} /></div></>
    if (tab === 'routes') return <RoutesTab sys={sys} />
    if (tab === 'dhcp') return <DHCPTab sys={sys} />
    if (tab === 'gateways') return <GatewaysTab sys={sys} />
    if (tab === 'certs') return <CertsTab sys={sys} />
    if (tab === 'updates') return platform === 'linux' ? <LinuxUpdatesTab sys={sys} agentId={agentId} /> : <UpdatesTab agentId={agentId} />
    if (tab === 'security') return <SecurityTab sys={sys} />
    if (tab === 'tasks') return <TasksTab agentId={agentId} agentName={agent?.name || ''} platform={platform} />
    if (tab === 'backups') return platform === 'linux' ? <PVEBackupsTab sys={sys} /> : <BackupsTab agentId={agentId} />
    if (tab === 'agent') return <AgentTab agent={data?.agent} status={data?.status} platform={platform} />
    if (tab === 'haproxy') return <HAProxyTab sys={sys} />
    if (tab === 'caddy') return <CaddyTab sys={sys} />
    return null
  }

  return (
    <Panel onClose={onClose}>
      {/* Header */}
      <div className="px-6 py-4 bg-gradient-to-r from-gray-800 to-gray-900 border-b border-gray-700">
        <div className="flex items-start justify-between">
          <div>
            <div className="flex items-center gap-3">
              <h2 className="text-lg font-bold text-white">{agent.name}</h2>
              <StatusBadge status={status} />
            </div>
            <CustomerAssign agent={agent} customers={customers} current={cust} onReload={onReload} />
            <div className="text-xs text-gray-500 mt-1">
              {agent.hostname} &middot; IP: {agent.ip} &middot; {platform === 'linux' ? 'Linux' : 'OPNsense'} &middot; {sys?.opnsense_version || agent.opnsense_version || '—'}
            </div>
          </div>
          <div className="flex items-center gap-2">
            <button
              onClick={async () => {
                if (!confirm(`Geraet "${agent.name}" wirklich loeschen?`)) return
                await api.deleteAgent(agent.id)
                if (onReload) onReload()
                onClose()
              }}
              className="text-gray-500 hover:text-red-400 transition-colors"
              title="Geraet loeschen"
            >
              <Trash2 className="w-4 h-4" />
            </button>
            <button onClick={onClose} className="text-gray-400 hover:text-white">
              <X className="w-5 h-5" />
            </button>
          </div>
        </div>

        {/* Main Category Tabs */}
        <div className="flex gap-1 mt-4 overflow-x-auto text-xs">
          {visibleMainTabs.map((cat) => (
            <button
              key={cat.id}
              onClick={() => handleMainTabChange(cat.id)}
              className={`px-4 py-1.5 whitespace-nowrap transition-colors border-b-2 ${
                mainTab === cat.id
                  ? 'text-orange-400 border-orange-400'
                  : 'text-gray-400 hover:text-gray-200 border-transparent'
              }`}
            >
              {cat.label}
            </button>
          ))}
        </div>
      </div>

      {/* Content area with optional sub-nav */}
      <div className="flex-1 flex overflow-hidden">
        {/* Sub-Navigation (left sidebar) — hidden for Uebersicht */}
        {mainTab !== 'uebersicht' && currentSubs.length > 0 && (
          <div className="w-44 shrink-0 bg-gray-900/50 border-r border-gray-800 overflow-y-auto py-3">
            <div className="px-4 mb-2">
              <span className="text-[10px] uppercase tracking-wider text-gray-500 font-semibold">
                {mainCategories.find(c => c.id === mainTab)?.label}
              </span>
            </div>
            {currentSubs.map((item) => {
              const Icon = item.icon
              const isActive = subTab === item.id
              return (
                <button
                  key={item.id}
                  onClick={() => setSubTab(item.id)}
                  className={`w-full flex items-center gap-2.5 px-4 py-2 text-sm transition-colors ${
                    isActive
                      ? 'text-orange-400 bg-orange-400/5 border-l-2 border-orange-400'
                      : 'text-gray-400 hover:text-white border-l-2 border-transparent'
                  }`}
                >
                  {Icon && <Icon className="w-4 h-4 shrink-0" />}
                  <span>{item.label}</span>
                </button>
              )
            })}
          </div>
        )}

        {/* Main content */}
        <div className="flex-1 overflow-y-auto p-6 space-y-4">
          {renderContent()}
        </div>
      </div>
    </Panel>
  )
}

function CustomerAssign({ agent, customers, current, onReload }) {
  const [editing, setEditing] = useState(false)
  const [saving, setSaving] = useState(false)

  const handleChange = async (e) => {
    const val = e.target.value
    setSaving(true)
    try {
      if (val === '') {
        await api.unassignCustomer(agent.id)
      } else {
        await api.assignCustomer(agent.id, parseInt(val))
      }
      if (onReload) onReload()
    } catch (err) {
      console.error(err)
    } finally {
      setSaving(false)
      setEditing(false)
    }
  }

  if (editing) {
    return (
      <div className="flex items-center gap-2 mt-0.5">
        <select
          value={agent.customer_id || ''}
          onChange={handleChange}
          disabled={saving}
          className="bg-gray-900 border border-gray-700 rounded px-2 py-1 text-sm text-white focus:outline-none focus:border-orange-500"
          autoFocus
          onBlur={() => !saving && setEditing(false)}
        >
          <option value="">— Nicht zugewiesen —</option>
          {customers.sort((a, b) => a.number.localeCompare(b.number)).map((c) => (
            <option key={c.id} value={c.id}>{c.number} — {c.name}</option>
          ))}
        </select>
        {saving && <span className="text-xs text-gray-500">Speichere...</span>}
      </div>
    )
  }

  return (
    <div
      className="text-sm mt-0.5 cursor-pointer hover:underline"
      onClick={() => setEditing(true)}
      title="Kunde aendern"
    >
      {current ? (
        <span className="text-orange-400">{current.number} — {current.name}</span>
      ) : (
        <span className="text-gray-500 italic">Kein Kunde zugewiesen (klicken zum Zuweisen)</span>
      )}
    </div>
  )
}

function Panel({ onClose, children }) {
  return (
    <>
      <div className="fixed inset-0 z-40 bg-black/50" onClick={onClose} />
      <div className="fixed inset-y-0 right-0 z-50 w-full max-w-6xl bg-gray-900 border-l border-gray-800 flex flex-col shadow-2xl animate-slide-in">
        {children}
      </div>
      <style>{`
        @keyframes slideIn { from { transform: translateX(100%); } to { transform: translateX(0); } }
        .animate-slide-in { animation: slideIn 0.2s ease-out; }
      `}</style>
    </>
  )
}

function GatewaysTab({ sys }) {
  const gateways = sys.gateways || []
  if (gateways.length === 0) return <div className="text-gray-500">Keine Gateways</div>
  return (
    <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 overflow-hidden">
      <table className="w-full text-sm">
        <thead>
          <tr className="text-left text-gray-500 text-xs border-b border-gray-700">
            <th className="px-3 py-2">Name</th>
            <th className="px-3 py-2">Gateway</th>
            <th className="px-3 py-2">Status</th>
            <th className="px-3 py-2">RTT</th>
            <th className="px-3 py-2">Loss</th>
          </tr>
        </thead>
        <tbody className="divide-y divide-gray-700/50">
          {gateways.map((gw) => (
            <tr key={gw.name}>
              <td className="px-3 py-2 text-white">{gw.name}</td>
              <td className="px-3 py-2 text-gray-400">{gw.gateway || gw.address}</td>
              <td className="px-3 py-2">
                <span className={gwColor(gw.status)}>
                  {gw.status || '—'}
                </span>
              </td>
              <td className="px-3 py-2 text-gray-400">{gw.delay || '—'}</td>
              <td className="px-3 py-2 text-gray-400">{gw.loss || '—'}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  )
}

function Sparkline({ data, height = 40, color = '#3b82f6' }) {
  if (!data || data.length < 2) return null
  const vals = data.map(d => d.value)
  const min = Math.min(...vals)
  const max = Math.max(...vals)
  const range = max - min || 1
  const w = 200
  const h = height
  const pts = vals.map((v, i) => {
    const x = (i / (vals.length - 1)) * w
    const y = h - ((v - min) / range) * (h - 4) - 2
    return `${x.toFixed(1)},${y.toFixed(1)}`
  }).join(' ')
  return (
    <svg width={w} height={h} viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none">
      <polyline points={pts} fill="none" stroke={color} strokeWidth="1.5" strokeLinejoin="round" strokeLinecap="round" />
    </svg>
  )
}

function MetricCard({ icon: Icon, label, value, sub, bar, barColor, chart }) {
  return (
    <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-4">
      <div className="flex items-start justify-between">
        <div className="flex-1 min-w-0">
          <div className="flex items-center gap-2 text-gray-500 mb-2">
            {Icon && <Icon className="w-4 h-4" />}
            <span className="text-xs uppercase">{label}</span>
          </div>
          <div className="text-xl font-bold text-white">{value}</div>
          {sub && <div className="text-xs text-gray-500 mt-0.5">{sub}</div>}
          {bar !== undefined && bar !== null && (
            <div className="mt-2 h-1.5 bg-gray-700 rounded overflow-hidden">
              <div className={`h-full rounded ${barColor || 'bg-blue-500'}`} style={{ width: `${Math.min(bar, 100)}%` }} />
            </div>
          )}
        </div>
        {chart && (
          <div className="ml-3 opacity-70 flex-shrink-0">
            {chart}
          </div>
        )}
      </div>
    </div>
  )
}

function useMetricChart(agentId, metric) {
  const [chartData, setChartData] = useState([])
  useEffect(() => {
    if (!agentId) return
    const from = new Date(Date.now() - 8 * 60 * 60 * 1000).toISOString()
    api.getMetrics(agentId, metric, `&from=${from}&limit=200`)
      .then(data => { if (Array.isArray(data)) setChartData(data) })
      .catch(() => {})
  }, [agentId, metric])
  return chartData
}

function PFStatesCard({ agentId, sys }) {
  const chartData = useMetricChart(agentId, 'pf_states_current')
  if (!sys?.pf_states) return null
  const pf = sys.pf_states
  const usedPct = pf.hard_limit > 0 ? (pf.current_entries / pf.hard_limit * 100) : 0
  const barColor = usedPct > 90 ? 'bg-red-500' : usedPct > 70 ? 'bg-yellow-500' : 'bg-green-500'
  return (
    <MetricCard
      icon={Shield} label="PF States"
      value={pf.hard_limit > 0
        ? `${pf.current_entries.toLocaleString('de-DE')} / ${pf.hard_limit.toLocaleString('de-DE')}`
        : `${pf.current_entries.toLocaleString('de-DE')}`}
      sub={`Search: ${pf.search_rate?.toFixed(1)}/s · Insert: ${pf.insert_rate?.toFixed(1)}/s`}
      bar={pf.hard_limit > 0 ? usedPct : null} barColor={barColor}
      chart={<Sparkline data={chartData} height={44} color="#3b82f6" />}
    />
  )
}

function CpuCard({ agentId, sys }) {
  const chartData = useMetricChart(agentId, 'cpu_usage')
  const cpuPct = sys?.cpu?.usage_percent
  const barColor = cpuPct > 90 ? 'bg-red-500' : cpuPct > 70 ? 'bg-yellow-500' : cpuPct > 50 ? 'bg-orange-500' : 'bg-green-500'
  return (
    <MetricCard
      icon={Cpu} label="CPU Auslastung"
      value={cpuPct != null ? `${cpuPct.toFixed(1)}%` : '—'}
      sub={sys?.cpu?.model} bar={cpuPct} barColor={barColor}
      chart={<Sparkline data={chartData} height={44} color="#f97316" />}
    />
  )
}

function RamCard({ agentId, sys }) {
  const chartData = useMetricChart(agentId, 'memory_used_percent')
  const ramPct = sys?.memory?.total_bytes > 0
    ? (sys.memory.used_bytes / sys.memory.total_bytes * 100) : null
  const barColor = ramPct > 90 ? 'bg-red-500' : ramPct > 70 ? 'bg-yellow-500' : ramPct > 50 ? 'bg-orange-500' : 'bg-green-500'
  return (
    <MetricCard
      icon={MemoryStick} label="RAM Auslastung"
      value={ramPct != null ? `${ramPct.toFixed(1)}%` : '—'}
      sub={sys?.memory ? `${formatBytes(sys.memory.used_bytes)} / ${formatBytes(sys.memory.total_bytes)}` : ''}
      bar={ramPct} barColor={barColor}
      chart={<Sparkline data={chartData} height={44} color="#a855f7" />}
    />
  )
}

function OverviewTab({ sys, agentId }) {
  const rootDisk = sys.disks?.find((d) => d.mount_point === '/')
  const diskPct = rootDisk && rootDisk.total_bytes > 0
    ? (rootDisk.used_bytes / rootDisk.total_bytes * 100) : null
  const ramPct = sys.memory?.total_bytes > 0
    ? (sys.memory.used_bytes / sys.memory.total_bytes * 100) : null
  const cpuPct = sys.cpu?.usage_percent

  const barColor = (v) => v > 90 ? 'bg-red-500' : v > 70 ? 'bg-yellow-500' : v > 50 ? 'bg-orange-500' : 'bg-green-500'

  const ifaceCount = sys.network_interfaces?.filter((i) => ['active', 'up'].includes(i.status)).length || 0
  const gwCount = sys.gateways?.length || 0
  const wgCount = (sys.wireguard || []).reduce((n, wg) => n + (wg.peers?.length || 0), 0) || sys.wireguard_peers?.length || 0
  const routeCount = sys.routes?.length || 0
  const certCount = sys.certificates?.length || 0
  const svcRunning = sys.services?.filter((s) => s.running || s.status === 'running').length || 0
  const svcTotal = sys.services?.length || 0

  return (
    <>
      <h3 className="text-sm font-medium text-gray-300">System-Metriken</h3>
      <div className="grid grid-cols-2 gap-3">
        <CpuCard agentId={agentId} sys={sys} />
        <RamCard agentId={agentId} sys={sys} />
        <MetricCard icon={HardDrive} label="Festplatte" value={diskPct != null ? `${diskPct.toFixed(1)}%` : '—'}
          sub={rootDisk ? `${formatBytes(rootDisk.used_bytes)} / ${formatBytes(rootDisk.total_bytes)}` : ''}
          bar={diskPct} barColor={barColor(diskPct || 0)} />
        <MetricCard icon={Clock} label="Uptime" value={sys.uptime_seconds ? formatUptime(sys.uptime_seconds) : '—'} />
        <PFStatesCard agentId={agentId} sys={sys} />
      </div>

      <h3 className="text-sm font-medium text-gray-300 mt-4">System Status</h3>
      <div className="grid grid-cols-4 gap-3">
        <StatusCard icon={Shield} value={sys.opnsense_version || '—'} label="OPNsense" />
        <StatusCard icon={Network} value={ifaceCount} label="Interfaces" />
        <StatusCard icon={Globe} value={gwCount} label="Gateways" />
        <StatusCard icon={Wifi} value={wgCount} label="VPN Tunnel" />
        <StatusCard icon={Route} value={routeCount} label="Routen" />
        <StatusCard icon={Key} value={certCount} label="Zertifikate" />
        <StatusCard value={`${svcRunning}/${svcTotal}`} label="Dienste" />
      </div>

      {/* Lizenz */}
      {sys.license && (
        <>
          <h3 className="text-sm font-medium text-gray-300 mt-4">Lizenz</h3>
          <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-4">
            <div className="flex items-center justify-between">
              <div>
                <div className="text-white font-medium">{sys.license.product_name || 'OPNsense'}</div>
                {sys.license.subscription && (
                  <div className="text-xs text-gray-500 mt-1 font-mono">{sys.license.subscription}</div>
                )}
              </div>
              {sys.license.valid_to && (
                <div className="text-right">
                  <div className={`text-lg font-bold ${
                    sys.license.days_remaining < 30 ? 'text-red-400' :
                    sys.license.days_remaining < 90 ? 'text-yellow-400' :
                    'text-green-400'
                  }`}>
                    {sys.license.days_remaining > 0 ? `${sys.license.days_remaining} Tage` : 'Abgelaufen'}
                  </div>
                  <div className="text-xs text-gray-500">gueltig bis {sys.license.valid_to}</div>
                </div>
              )}
            </div>
            {sys.license.valid_to && sys.license.days_remaining != null && (
              <div className="mt-3 w-full h-2 bg-gray-700 rounded overflow-hidden">
                <div
                  className={`h-full rounded ${
                    sys.license.days_remaining < 30 ? 'bg-red-500' :
                    sys.license.days_remaining < 90 ? 'bg-yellow-500' :
                    'bg-green-500'
                  }`}
                  style={{ width: `${Math.min(100, Math.max(2, sys.license.days_remaining / 365 * 100))}%` }}
                />
              </div>
            )}
          </div>
        </>
      )}

      {/* Gateways */}
      {sys.gateways && sys.gateways.length > 0 && (
        <>
          <h3 className="text-sm font-medium text-gray-300 mt-4">Gateways</h3>
          <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 overflow-hidden">
            <table className="w-full text-sm">
              <thead>
                <tr className="text-left text-gray-500 text-xs border-b border-gray-700">
                  <th className="px-3 py-2">Name</th>
                  <th className="px-3 py-2">Gateway</th>
                  <th className="px-3 py-2">Status</th>
                  <th className="px-3 py-2">RTT</th>
                  <th className="px-3 py-2">Loss</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-gray-700/50">
                {sys.gateways.map((gw) => (
                  <tr key={gw.name}>
                    <td className="px-3 py-2 text-white">{gw.name}</td>
                    <td className="px-3 py-2 text-gray-400">{gw.gateway || gw.address}</td>
                    <td className="px-3 py-2">
                      <span className={gwColor(gw.status)}>
                        {gw.status || '—'}
                      </span>
                    </td>
                    <td className="px-3 py-2 text-gray-400">{gw.delay || '—'}</td>
                    <td className="px-3 py-2 text-gray-400">{gw.loss || '—'}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </>
      )}
    </>
  )
}

function StatusCard({ icon: Icon, value, label }) {
  return (
    <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-3 text-center">
      {Icon && <Icon className="w-5 h-5 mx-auto text-gray-500 mb-1" />}
      <div className="text-lg font-bold text-white">{value}</div>
      <div className="text-xs text-gray-500">{label}</div>
    </div>
  )
}

const IFACE_RANGES = [
  { label: '8h',  hours: 8,        limit: 200 },
  { label: '24h', hours: 24,       limit: 400 },
  { label: '7d',  hours: 24 * 7,   limit: 500 },
]

function IfaceChartSingle({ agentId, ifaceName, range }) {
  const [rxData, setRxData] = useState([])
  const [txData, setTxData] = useState([])

  useEffect(() => {
    if (!agentId || !ifaceName) return
    setRxData([])
    setTxData([])
    const from = new Date(Date.now() - range.hours * 60 * 60 * 1000).toISOString()
    const params = `&from=${from}&limit=${range.limit}&tags=${encodeURIComponent(JSON.stringify({ interface: ifaceName }))}`
    api.getMetrics(agentId, 'interface_rx_bps', params).then(d => { if (Array.isArray(d)) setRxData(d) }).catch(() => {})
    api.getMetrics(agentId, 'interface_tx_bps', params).then(d => { if (Array.isArray(d)) setTxData(d) }).catch(() => {})
  }, [agentId, ifaceName, range])

  const formatBps = (v) => {
    if (v >= 1024 * 1024 * 1024) return `${(v / 1024 / 1024 / 1024).toFixed(1)} GB/s`
    if (v >= 1024 * 1024) return `${(v / 1024 / 1024).toFixed(1)} MB/s`
    if (v >= 1024) return `${(v / 1024).toFixed(1)} KB/s`
    return `${Math.round(v)} B/s`
  }

  if (rxData.length < 2 && txData.length < 2) {
    return (
      <div className="flex flex-col">
        <span className="text-xs text-gray-500 mb-1">{range.label}</span>
        <div className="text-xs text-gray-600 py-3 text-center bg-gray-800/30 rounded">Keine Daten</div>
      </div>
    )
  }

  const allVals = [...rxData.map(d => d.value), ...txData.map(d => d.value)]
  const maxVal = Math.max(...allVals, 1)
  const magnitude = Math.pow(10, Math.floor(Math.log10(maxVal)))
  const niceMax = Math.ceil(maxVal / magnitude) * magnitude

  const PAD_LEFT = 56
  const PAD_RIGHT = 8
  const PAD_TOP = 8
  const PAD_BOTTOM = 22
  const SVG_W = 600
  const SVG_H = 130
  const chartW = SVG_W - PAD_LEFT - PAD_RIGHT
  const chartH = SVG_H - PAD_TOP - PAD_BOTTOM

  const toX = (i, len) => PAD_LEFT + (i / Math.max(len - 1, 1)) * chartW
  const toY = (val) => PAD_TOP + chartH - (val / niceMax) * chartH
  const toPath = (data) => data.map((d, i) => `${toX(i, data.length).toFixed(1)},${toY(d.value).toFixed(1)}`).join(' ')

  const yTicks = [0, 0.5, 1.0].map(f => ({ val: niceMax * f, y: toY(niceMax * f) }))

  const fmtLabel = (iso) => {
    if (!iso) return ''
    const d = new Date(iso)
    if (range.hours > 24) return d.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' })
    return d.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' })
  }
  const allData = rxData.length >= txData.length ? rxData : txData
  const xTicks = allData.length >= 2
    ? [
        { label: fmtLabel(allData[0]?.time), x: toX(0, allData.length) },
        { label: fmtLabel(allData[Math.floor(allData.length / 2)]?.time), x: toX(Math.floor(allData.length / 2), allData.length) },
        { label: fmtLabel(allData.at(-1)?.time), x: toX(allData.length - 1, allData.length) },
      ]
    : []

  const lastRx = rxData.at(-1)?.value || 0
  const lastTx = txData.at(-1)?.value || 0

  return (
    <div className="flex flex-col">
      <div className="flex items-center justify-between mb-1">
        <span className="text-xs text-gray-500 font-medium">{range.label}</span>
        <div className="flex gap-3 text-xs">
          <span className="text-blue-400">↓ {formatBps(lastRx)}</span>
          <span className="text-green-400">↑ {formatBps(lastTx)}</span>
        </div>
      </div>
      <svg width="100%" viewBox={`0 0 ${SVG_W} ${SVG_H}`} preserveAspectRatio="xMidYMid meet" className="w-full" style={{ height: '130px' }}>
        {yTicks.map(({ val, y }) => (
          <g key={val}>
            <line x1={PAD_LEFT} y1={y.toFixed(1)} x2={SVG_W - PAD_RIGHT} y2={y.toFixed(1)} stroke="#374151" strokeWidth="0.5" strokeDasharray={val === 0 ? 'none' : '3,3'} />
            <text x={PAD_LEFT - 4} y={y + 4} textAnchor="end" fontSize="10" fill="#6b7280">{formatBps(val)}</text>
          </g>
        ))}
        {rxData.length >= 2 && <polygon points={[`${toX(0, rxData.length).toFixed(1)},${(PAD_TOP + chartH).toFixed(1)}`, ...rxData.map((d, i) => `${toX(i, rxData.length).toFixed(1)},${toY(d.value).toFixed(1)}`), `${toX(rxData.length - 1, rxData.length).toFixed(1)},${(PAD_TOP + chartH).toFixed(1)}`].join(' ')} fill="#3b82f620" />}
        {txData.length >= 2 && <polygon points={[`${toX(0, txData.length).toFixed(1)},${(PAD_TOP + chartH).toFixed(1)}`, ...txData.map((d, i) => `${toX(i, txData.length).toFixed(1)},${toY(d.value).toFixed(1)}`), `${toX(txData.length - 1, txData.length).toFixed(1)},${(PAD_TOP + chartH).toFixed(1)}`].join(' ')} fill="#22c55e18" />}
        {rxData.length >= 2 && <polyline points={toPath(rxData)} fill="none" stroke="#3b82f6" strokeWidth="1.5" strokeLinejoin="round" />}
        {txData.length >= 2 && <polyline points={toPath(txData)} fill="none" stroke="#22c55e" strokeWidth="1.5" strokeLinejoin="round" />}
        <line x1={PAD_LEFT} y1={PAD_TOP + chartH} x2={SVG_W - PAD_RIGHT} y2={PAD_TOP + chartH} stroke="#374151" strokeWidth="0.5" />
        {xTicks.map(({ label, x }, idx) => (
          <text key={idx} x={x} y={SVG_H - 4} textAnchor={idx === 0 ? 'start' : idx === xTicks.length - 1 ? 'end' : 'middle'} fontSize="10" fill="#6b7280">{label}</text>
        ))}
      </svg>
    </div>
  )
}

function IfaceChart({ agentId, ifaceName }) {
  return (
    <div className="mt-3 pt-3 border-t border-gray-700/50 space-y-4">
      <div className="flex items-center gap-4 text-xs">
        <span className="flex items-center gap-1"><span className="inline-block w-3 h-0.5 bg-blue-400 rounded" /><span className="text-blue-400">RX</span></span>
        <span className="flex items-center gap-1"><span className="inline-block w-3 h-0.5 bg-green-400 rounded" /><span className="text-green-400">TX</span></span>
      </div>
      {IFACE_RANGES.map(r => (
        <IfaceChartSingle key={r.label} agentId={agentId} ifaceName={ifaceName} range={r} />
      ))}
    </div>
  )
}

function fmtTime(iso) {
  if (!iso) return ''
  const d = new Date(iso)
  return d.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' })
}

function InterfacesTab({ sys, agentId }) {
  const [expanded, setExpanded] = useState(null)
  const ifaces = sys.network_interfaces || []
  return (
    <div className="space-y-3">
      <h3 className="text-sm font-medium text-gray-300">Netzwerk-Interfaces</h3>
      {ifaces.map((i) => {
        const isUp = i.status === 'active' || i.status === 'up'
        const ip = i.ip || i.addresses?.filter((a) => !a.includes(':')).join(', ') || ''
        const role = i.role || i.description || ''
        const isOpen = expanded === i.name
        return (
          <div
            key={i.name}
            className="bg-gray-800/50 rounded-lg border border-gray-700/50 px-5 py-4 cursor-pointer hover:border-gray-600/70 transition-colors"
            onClick={() => setExpanded(isOpen ? null : i.name)}
          >
            <div className="flex items-center gap-4">
              {/* Icon */}
              <div className="flex-shrink-0">
                <Network className={`w-7 h-7 ${isUp ? 'text-blue-400' : 'text-gray-600'}`} />
              </div>

              {/* Info */}
              <div className="flex-1 min-w-0">
                <div className="flex items-center gap-2">
                  <span className="text-white font-bold text-sm">{i.name}</span>
                  {role && (
                    <span className="text-xs px-1.5 py-0.5 rounded bg-blue-900/50 text-blue-300 border border-blue-800/50">
                      {role}
                    </span>
                  )}
                  {!isUp && (
                    <span className="text-xs px-1.5 py-0.5 rounded bg-gray-700 text-gray-400">
                      {i.status || 'down'}
                    </span>
                  )}
                </div>
                <div className="text-xs text-gray-400 mt-1 flex items-center gap-3">
                  {ip && <span>{ip}</span>}
                  {i.mac && <span className="text-gray-500 font-mono">{i.mac}</span>}
                </div>
              </div>

              {/* Traffic + Chevron */}
              <div className="flex items-center gap-3">
                <div className="flex-shrink-0 text-right text-xs">
                  <div className="text-gray-400">
                    <span className="text-blue-400">↓</span> {formatBytes(i.rx_bytes)}
                  </div>
                  <div className="text-gray-400 mt-0.5">
                    <span className="text-green-400">↑</span> {formatBytes(i.tx_bytes)}
                  </div>
                </div>
                {isOpen ? <ChevronDown className="w-4 h-4 text-gray-500" /> : <ChevronRight className="w-4 h-4 text-gray-500" />}
              </div>
            </div>

            {/* Expandierter Chart */}
            {isOpen && <IfaceChart agentId={agentId} ifaceName={i.name} />}
          </div>
        )
      })}
    </div>
  )
}

const SERVICE_DESCRIPTIONS = {
  configd: 'Configuration Daemon',
  dhcpd: 'DHCP Server',
  dpinger: 'Gateway Monitor',
  openssh: 'Secure Shell',
  syslogd: 'System Logger',
  unbound: 'DNS Resolver',
  openvpn: 'OpenVPN',
  cron: 'Cron Daemon',
  ntpd: 'NTP Daemon',
  'syslog-ng': 'Syslog-NG',
  haproxy: 'HAProxy Load Balancer',
  nginx: 'Nginx Webserver',
  squid: 'Squid Proxy',
  suricata: 'Suricata IDS/IPS',
  wireguard: 'WireGuard VPN',
  pf: 'Packet Filter',
  routing: 'Routing Daemon',
  radvd: 'Router Advertisement',
  dnsmasq: 'DNS Forwarder',
  monit: 'Process Monitor',
  collectd: 'System Statistics',
  rmm_agent: 'RMM Agent',
}

function isRunning(svc) {
  return svc.running || svc.status === 'running'
}

function ServicesTab({ sys }) {
  const services = sys.services || []
  const running = services.filter(isRunning)
  const stopped = services.filter((s) => !isRunning(s))
  const sorted = [...services].sort((a, b) =>
    isRunning(a) === isRunning(b) ? a.name.localeCompare(b.name) : isRunning(a) ? -1 : 1
  )
  return (
    <div className="space-y-3">
      <div className="text-sm text-gray-400">{running.length} aktiv / {stopped.length} inaktiv</div>
      <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 overflow-hidden">
        <table className="w-full text-sm">
          <thead>
            <tr className="text-left text-gray-500 text-xs border-b border-gray-700">
              <th className="px-4 py-2 font-medium">Dienst</th>
              <th className="px-4 py-2 font-medium">Beschreibung</th>
              <th className="px-4 py-2 font-medium text-right">Status</th>
            </tr>
          </thead>
          <tbody className="divide-y divide-gray-700/50">
            {sorted.map((svc) => {
              const up = isRunning(svc)
              return (
                <tr key={svc.name}>
                  <td className="px-4 py-2.5 text-white font-medium">{svc.name}</td>
                  <td className="px-4 py-2.5 text-gray-400">{svc.description || SERVICE_DESCRIPTIONS[svc.name] || '—'}</td>
                  <td className="px-4 py-2.5 text-right">
                    <span
                      className={`inline-flex items-center gap-1.5 text-xs font-medium px-3 py-1 rounded ${
                        up
                          ? 'bg-green-900/40 text-green-400 border border-green-700/50'
                          : 'bg-gray-800 text-gray-500 border border-gray-700'
                      }`}
                    >
                      <span className={`w-1.5 h-1.5 rounded-full ${up ? 'bg-green-400' : 'bg-gray-500'}`} />
                      {up ? 'running' : 'stopped'}
                    </span>
                  </td>
                </tr>
              )
            })}
          </tbody>
        </table>
      </div>
    </div>
  )
}

function VPNTab({ sys }) {
  // Flatten: wireguard is array of interfaces, each with peers
  const wgInterfaces = sys.wireguard || []
  const allPeers = []
  wgInterfaces.forEach((wg) => {
    (wg.peers || []).forEach((p) => {
      allPeers.push({ ...p, iface: wg.interface, listen_port: wg.listen_port, iface_pubkey: wg.public_key })
    })
  })
  // Fallback for flat wireguard_peers
  const peers = allPeers.length > 0 ? allPeers : (sys.wireguard_peers || [])

  if (peers.length === 0) return <div className="text-gray-500">Keine WireGuard-Peers</div>
  return (
    <div className="space-y-3">
      {wgInterfaces.length > 0 && (
        <div className="text-sm text-gray-400">{wgInterfaces.length} Interface(s), {peers.length} Peer(s)</div>
      )}
      <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 overflow-hidden">
        <table className="w-full text-sm">
          <thead>
            <tr className="text-left text-gray-500 text-xs border-b border-gray-700">
              <th className="px-3 py-2">Interface</th>
              <th className="px-3 py-2">Public Key</th>
              <th className="px-3 py-2">Endpoint</th>
              <th className="px-3 py-2">Allowed IPs</th>
              <th className="px-3 py-2">Transfer</th>
              <th className="px-3 py-2">Handshake</th>
              <th className="px-3 py-2">Status</th>
            </tr>
          </thead>
          <tbody className="divide-y divide-gray-700/50">
            {peers.map((p, i) => {
              const isActive = p.status === 'active' || p.handshake_age
              return (
                <tr key={i}>
                  <td className="px-3 py-2 text-white font-mono text-xs">{p.iface || p.interface || '—'}</td>
                  <td className="px-3 py-2 text-gray-400 font-mono text-xs">{(p.public_key || '—').substring(0, 16)}...</td>
                  <td className="px-3 py-2 text-gray-400 text-xs">{p.endpoint || '—'}</td>
                  <td className="px-3 py-2 text-gray-400 text-xs">{(p.allowed_ips || []).join(', ') || '—'}</td>
                  <td className="px-3 py-2 text-gray-400 text-xs">
                    {p.transfer_rx_bytes || p.transfer_rx
                      ? `↓ ${formatBytes(p.transfer_rx_bytes || p.transfer_rx)} / ↑ ${formatBytes(p.transfer_tx_bytes || p.transfer_tx)}`
                      : '—'}
                  </td>
                  <td className="px-3 py-2 text-gray-400 text-xs">{p.handshake_age || p.latest_handshake || '—'}</td>
                  <td className="px-3 py-2">
                    <span className={`inline-flex items-center gap-1.5 text-xs font-medium px-2 py-0.5 rounded ${
                      isActive
                        ? 'bg-green-900/40 text-green-400 border border-green-700/50'
                        : 'bg-gray-800 text-gray-500 border border-gray-700'
                    }`}>
                      <span className={`w-1.5 h-1.5 rounded-full ${isActive ? 'bg-green-400' : 'bg-gray-500'}`} />
                      {isActive ? 'aktiv' : 'inaktiv'}
                    </span>
                  </td>
                </tr>
              )
            })}
          </tbody>
        </table>
      </div>
    </div>
  )
}

function TunnelTab({ agentId, agent }) {
  const [tunnels, setTunnels] = useState([])
  const [loading, setLoading] = useState(true)
  const [creating, setCreating] = useState(null) // track which quick-button is active
  const [customOpen, setCustomOpen] = useState(false)
  const [customHost, setCustomHost] = useState('127.0.0.1')
  const [customPort, setCustomPort] = useState('')
  const [error, setError] = useState('')
  const [sshCopied, setSshCopied] = useState(null)
  const [terminalOpen, setTerminalOpen] = useState(false)
  const [scriptOpen, setScriptOpen] = useState(false)

  const backendHost = useSettingsStore.getState().getBackendHost()

  const loadTunnels = () => {
    api.getTunnels(agentId)
      .then((resp) => {
        const list = resp?.tunnels || resp?.data?.tunnels || resp?.data || resp || []
        setTunnels(Array.isArray(list) ? list : [])
      })
      .catch(() => setTunnels([]))
      .finally(() => setLoading(false))
  }

  useEffect(() => { loadTunnels() }, [agentId])
  useEffect(() => {
    if (tunnels.length > 0) {
      const iv = setInterval(loadTunnels, 10000)
      return () => clearInterval(iv)
    }
  }, [tunnels.length, agentId])

  const openTunnel = async (targetHost, targetPort, label) => {
    setError('')
    setCreating(label)
    try {
      const resp = await api.openTunnel(agentId, targetHost, targetPort)
      const data = resp?.data || resp
      // Reload tunnel list
      loadTunnels()
      // Auto-open for known services
      if (data?.proxy_port) {
        setTimeout(() => {
          if (targetPort === 4444) {
            window.open(`https://${backendHost}:${data.proxy_port}`, '_blank')
          } else if (targetPort === 22) {
            const cmd = `ssh root@${backendHost} -p ${data.proxy_port}`
            copyToClipboard(cmd)
            setSshCopied(data.proxy_port)
            setTimeout(() => setSshCopied(null), 4000)
          }
        }, 1000)
      }
      return data
    } catch (e) {
      setError(e.message)
    } finally {
      setCreating(null)
    }
  }

  const closeTunnel = async (tunnelId) => {
    try {
      await api.closeTunnel(agentId, tunnelId)
      setTunnels((prev) => prev.filter((t) => t.id !== tunnelId && t.tunnel_id !== tunnelId))
    } catch (e) {
      setError(e.message)
    }
  }

  const handleCustom = () => {
    const port = parseInt(customPort)
    if (!port || port < 1 || port > 65535) return
    openTunnel(customHost, port, 'custom')
    setCustomOpen(false)
    setCustomPort('')
  }

  return (
    <div className="space-y-4">
      {terminalOpen && (
        <TerminalModal agentId={agentId} agentName={agent?.name} onClose={() => setTerminalOpen(false)} />
      )}
      {scriptOpen && (
        <ScriptModal agentId={agentId} agentName={agent?.name} onClose={() => setScriptOpen(false)} />
      )}

      {/* Quick Buttons */}
      <div className="flex items-center gap-3 flex-wrap">
        <span className="text-sm text-gray-400">Schnellzugriff:</span>
        <button
          onClick={() => openTunnel('127.0.0.1', 4444, 'webgui')}
          disabled={creating === 'webgui'}
          className="flex items-center gap-1.5 px-3 py-1.5 bg-orange-600 hover:bg-orange-700 disabled:bg-orange-800 disabled:opacity-50 rounded text-sm text-white transition-colors"
        >
          <MonitorSmartphone className="w-4 h-4" />
          {creating === 'webgui' ? 'Verbinde...' : 'WebGUI (4444)'}
        </button>
        <button
          onClick={() => openTunnel('127.0.0.1', 22, 'ssh')}
          disabled={creating === 'ssh'}
          className="flex items-center gap-1.5 px-3 py-1.5 bg-blue-600 hover:bg-blue-700 disabled:bg-blue-800 disabled:opacity-50 rounded text-sm text-white transition-colors"
        >
          <Terminal className="w-4 h-4" />
          {creating === 'ssh' ? 'Verbinde...' : 'SSH (22)'}
        </button>
        <button
          onClick={() => setTerminalOpen(true)}
          className="flex items-center gap-1.5 px-3 py-1.5 bg-green-700 hover:bg-green-600 rounded text-sm text-white transition-colors"
        >
          <Terminal className="w-4 h-4" />
          Web Terminal
        </button>
        <button
          onClick={() => setScriptOpen(true)}
          className="flex items-center gap-1.5 px-3 py-1.5 bg-purple-700 hover:bg-purple-600 rounded text-sm text-white transition-colors"
        >
          <FileCode className="w-4 h-4" />
          Script
        </button>
        <button
          onClick={() => setCustomOpen(!customOpen)}
          className="flex items-center gap-1.5 px-3 py-1.5 bg-gray-700 hover:bg-gray-600 rounded text-sm text-gray-300 transition-colors"
        >
          <Plus className="w-4 h-4" />
          Benutzerdefiniert
        </button>
      </div>

      {/* Custom Tunnel Form */}
      {customOpen && (
        <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-4 flex items-end gap-3">
          <div>
            <label className="block text-xs text-gray-400 mb-1">Ziel-Host</label>
            <input
              type="text"
              value={customHost}
              onChange={(e) => setCustomHost(e.target.value)}
              className="bg-gray-900 border border-gray-700 rounded px-3 py-2 text-sm text-white w-40 focus:outline-none focus:border-orange-500"
            />
          </div>
          <div>
            <label className="block text-xs text-gray-400 mb-1">Port</label>
            <input
              type="number"
              value={customPort}
              onChange={(e) => setCustomPort(e.target.value)}
              placeholder="z.B. 8080"
              className="bg-gray-900 border border-gray-700 rounded px-3 py-2 text-sm text-white w-28 focus:outline-none focus:border-orange-500"
              onKeyDown={(e) => e.key === 'Enter' && handleCustom()}
            />
          </div>
          <button
            onClick={handleCustom}
            className="px-4 py-2 bg-green-600 hover:bg-green-700 rounded text-sm text-white transition-colors"
          >
            Verbinden
          </button>
        </div>
      )}

      {sshCopied && (
        <div className="text-sm text-green-400 bg-green-900/20 rounded px-3 py-2 border border-green-800/50 flex items-center gap-2">
          <Terminal className="w-4 h-4" />
          SSH-Befehl kopiert — in CMD/Terminal einfuegen und ausfuehren
        </div>
      )}
      {error && <div className="text-sm text-red-400 bg-red-900/20 rounded px-3 py-2 border border-red-800/50">{error}</div>}

      {/* Active Tunnels */}
      <div>
        <h3 className="text-sm font-medium text-gray-300 mb-2">Aktive Tunnel</h3>
        {loading ? (
          <div className="text-gray-500">Laden...</div>
        ) : tunnels.length === 0 ? (
          <div className="text-gray-500 bg-gray-800/30 rounded-lg border border-gray-800 px-4 py-6 text-center text-sm">
            Keine aktiven Tunnel
          </div>
        ) : (
          <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 overflow-hidden">
            <table className="w-full text-sm">
              <thead>
                <tr className="text-left text-gray-500 text-xs border-b border-gray-700">
                  <th className="px-3 py-2">Ziel</th>
                  <th className="px-3 py-2">Lokaler Zugang</th>
                  <th className="px-3 py-2">Status</th>
                  <th className="px-3 py-2">Erstellt</th>
                  <th className="px-3 py-2 text-right">Aktionen</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-gray-700/50">
                {tunnels.map((t) => {
                  const tid = t.id || t.tunnel_id
                  const proxyPort = t.proxy_port || t.local_port
                  const target = t.target_host && t.target_port
                    ? `${t.target_host}:${t.target_port}`
                    : t.target || '—'
                  const proxyUrl = proxyPort ? `${backendHost}:${proxyPort}` : '—'
                  const isWebGUI = t.target_port === 4444 || t.target_port === '4444'
                  const isSSH = t.target_port === 22 || t.target_port === '22'

                  return (
                    <tr key={tid}>
                      <td className="px-3 py-2.5 text-white font-mono text-xs">{target}</td>
                      <td className="px-3 py-2.5">
                        <div className="flex items-center gap-2">
                          <span className="text-gray-400 font-mono text-xs">{proxyUrl}</span>
                          {isWebGUI && proxyPort && (
                            <a
                              href={`https://${backendHost}:${proxyPort}`}
                              target="_blank"
                              rel="noopener"
                              className="text-orange-400 hover:text-orange-300"
                              title="WebGUI oeffnen"
                            >
                              <ExternalLink className="w-3.5 h-3.5" />
                            </a>
                          )}
                          {isSSH && proxyPort && (
                            <button
                              onClick={() => {
                                const cmd = `ssh root@${backendHost} -p ${proxyPort}`
                                copyToClipboard(cmd)
                                setSshCopied(proxyPort)
                                setTimeout(() => setSshCopied(null), 3000)
                              }}
                              className={`inline-flex items-center gap-1 text-xs px-1.5 py-0.5 rounded transition-colors ${
                                sshCopied === proxyPort
                                  ? 'bg-green-900/30 text-green-400 border border-green-700/50'
                                  : 'bg-blue-900/30 text-blue-400 border border-blue-700/50 hover:bg-blue-900/50'
                              }`}
                              title={`ssh root@${backendHost} -p ${proxyPort}`}
                            >
                              <Terminal className="w-3 h-3" />
                              {sshCopied === proxyPort ? 'Kopiert!' : 'SSH kopieren'}
                            </button>
                          )}
                        </div>
                      </td>
                      <td className="px-3 py-2.5">
                        <span className="inline-flex items-center gap-1.5 text-xs text-green-400">
                          <span className="w-1.5 h-1.5 rounded-full bg-green-400 animate-pulse" />
                          aktiv
                        </span>
                      </td>
                      <td className="px-3 py-2.5 text-gray-500 text-xs">
                        {t.created_at ? new Date(t.created_at).toLocaleString('de-DE') : '—'}
                      </td>
                      <td className="px-3 py-2.5 text-right">
                        <button
                          onClick={() => closeTunnel(tid)}
                          className="text-red-400 hover:text-red-300 p-1 rounded hover:bg-red-900/30 transition-colors"
                          title="Tunnel schliessen"
                        >
                          <Unplug className="w-4 h-4" />
                        </button>
                      </td>
                    </tr>
                  )
                })}
              </tbody>
            </table>
          </div>
        )}
      </div>

      {/* Hint */}
      <div className="text-xs text-gray-600 mt-2">
        Tunnel werden ueber den RMM-Backend-Server ({backendHost}) geroutet. WebGUI-Tunnel oeffnen automatisch ein neues Browserfenster.
      </div>
    </div>
  )
}

function WireGuardTab({ agentId, sys }) {
  const [peers, setPeers] = useState([])
  const [loading, setLoading] = useState(true)
  const [adding, setAdding] = useState(false)
  const [newPeer, setNewPeer] = useState({ name: '', dns: '10.172.100.210, 10.172.100.220' })
  const [result, setResult] = useState(null)
  const [copied, setCopied] = useState(false)
  const [error, setError] = useState('')

  const [noInstance, setNoInstance] = useState(false)

  const loadPeers = () => {
    setLoading(true)
    setNoInstance(false)
    api.getWgPeers(agentId)
      .then((resp) => {
        const d = resp?.data || resp || {}
        setPeers(Array.isArray(d.peers) ? d.peers : Array.isArray(d) ? d : [])
      })
      .catch((e) => {
        setPeers([])
        if (e.message && e.message.includes('nicht gefunden')) setNoInstance(true)
      })
      .finally(() => setLoading(false))
  }

  useEffect(() => { loadPeers() }, [agentId])

  const handleAdd = async () => {
    if (!newPeer.name.trim()) return
    setError('')
    try {
      const resp = await api.addWgPeer(agentId, {
        instance: 'ALWAYSON_VPN',
        name: newPeer.name.trim(),
        dns: newPeer.dns.trim(),
      })
      setResult(resp?.data || resp)
      setAdding(false)
      setNewPeer({ name: '', dns: '10.172.100.210, 10.172.100.220' })
      loadPeers()
    } catch (e) {
      setError(e.message)
    }
  }

  const handleDelete = async (uuid, name) => {
    if (!confirm(`Peer "${name || uuid}" wirklich loeschen?`)) return
    try {
      await api.deleteWgPeer(agentId, uuid)
      setResult(null)
      loadPeers()
    } catch (e) {
      setError(e.message)
    }
  }

  const copyConfig = (text) => {
    copyToClipboard(text)
    setCopied(true)
    setTimeout(() => setCopied(false), 2000)
  }

  if (noInstance) {
    return <div className="text-gray-500">Kein ALWAYSON_VPN Tunnel auf diesem Geraet gefunden.</div>
  }

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between">
        <div className="text-sm text-gray-400">
          ALWAYSON_VPN Peer-Verwaltung
        </div>
        <button
          onClick={() => { setAdding(!adding); setResult(null); setError('') }}
          className="flex items-center gap-1.5 px-3 py-1.5 bg-orange-600 hover:bg-orange-700 rounded text-sm text-white transition-colors"
        >
          <Plus className="w-4 h-4" />
          Neuer Peer
        </button>
      </div>

      {/* Add Peer Form */}
      {adding && (
        <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-4 space-y-3">
          <div>
            <label className="block text-xs text-gray-400 mb-1">Name / Beschreibung</label>
            <input
              type="text"
              value={newPeer.name}
              onChange={(e) => setNewPeer({ ...newPeer, name: e.target.value })}
              placeholder="z.B. Laptop-Christian"
              className="w-full bg-gray-900 border border-gray-700 rounded px-3 py-2 text-sm text-white placeholder-gray-600 focus:outline-none focus:border-orange-500"
              autoFocus
            />
          </div>
          <div>
            <label className="block text-xs text-gray-400 mb-1">DNS Server</label>
            <input
              type="text"
              value={newPeer.dns}
              onChange={(e) => setNewPeer({ ...newPeer, dns: e.target.value })}
              className="w-full bg-gray-900 border border-gray-700 rounded px-3 py-2 text-sm text-white placeholder-gray-600 focus:outline-none focus:border-orange-500"
            />
          </div>
          {error && <div className="text-sm text-red-400">{error}</div>}
          <div className="flex gap-2">
            <button
              onClick={handleAdd}
              className="px-4 py-1.5 bg-green-600 hover:bg-green-700 rounded text-sm text-white transition-colors"
            >
              Anlegen
            </button>
            <button
              onClick={() => { setAdding(false); setError('') }}
              className="px-4 py-1.5 bg-gray-700 hover:bg-gray-600 rounded text-sm text-gray-300 transition-colors"
            >
              Abbrechen
            </button>
          </div>
        </div>
      )}

      {/* New Peer Result / Config */}
      {result && result.client_config && (
        <div className="bg-gray-800/50 rounded-lg border border-green-700/50 p-4 space-y-2">
          <div className="flex items-center justify-between">
            <span className="text-sm text-green-400 font-medium">Peer erstellt — Client-Konfiguration:</span>
            <button
              onClick={() => copyConfig(result.client_config)}
              className="flex items-center gap-1.5 px-2 py-1 bg-gray-700 hover:bg-gray-600 rounded text-xs text-gray-300 transition-colors"
            >
              {copied ? <Check className="w-3.5 h-3.5 text-green-400" /> : <Copy className="w-3.5 h-3.5" />}
              {copied ? 'Kopiert' : 'Kopieren'}
            </button>
          </div>
          <pre className="bg-gray-900 rounded p-3 text-xs text-gray-300 font-mono overflow-x-auto whitespace-pre-wrap">
            {result.client_config}
          </pre>
          {result.assigned_ip && (
            <div className="text-xs text-gray-400">Zugewiesene IP: <span className="text-white">{result.assigned_ip}</span></div>
          )}
        </div>
      )}

      {/* Peer List */}
      {loading ? (
        <div className="text-gray-500">Laden...</div>
      ) : peers.length === 0 ? (
        <div className="text-gray-500">Keine Peers konfiguriert</div>
      ) : (
        <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 overflow-hidden">
          <table className="w-full text-sm">
            <thead>
              <tr className="text-left text-gray-500 text-xs border-b border-gray-700">
                <th className="px-3 py-2">Name</th>
                <th className="px-3 py-2">Public Key</th>
                <th className="px-3 py-2">Tunnel IP</th>
                <th className="px-3 py-2">Enabled</th>
                <th className="px-3 py-2 text-right">Aktionen</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-gray-700/50">
              {peers.map((p) => (
                <tr key={p.uuid || p.public_key}>
                  <td className="px-3 py-2.5 text-white">{p.name || p.description || '—'}</td>
                  <td className="px-3 py-2.5 text-gray-400 font-mono text-xs">{(p.public_key || p.pubkey || '—').substring(0, 20)}...</td>
                  <td className="px-3 py-2.5 text-gray-400 font-mono text-xs">{p.tunnel_address || p.allowed_ips || '—'}</td>
                  <td className="px-3 py-2.5">
                    <span className={`inline-flex items-center gap-1.5 text-xs ${p.enabled !== false ? 'text-green-400' : 'text-gray-500'}`}>
                      <span className={`w-1.5 h-1.5 rounded-full ${p.enabled !== false ? 'bg-green-400' : 'bg-gray-500'}`} />
                      {p.enabled !== false ? 'Ja' : 'Nein'}
                    </span>
                  </td>
                  <td className="px-3 py-2.5 text-right">
                    <button
                      onClick={() => handleDelete(p.uuid, p.name || p.description)}
                      className="text-red-400 hover:text-red-300 p-1 rounded hover:bg-red-900/30 transition-colors"
                      title="Peer loeschen"
                    >
                      <Trash2 className="w-4 h-4" />
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  )
}

function RoutesTab({ sys }) {
  const routes = sys.routes || []
  if (routes.length === 0) return <div className="text-gray-500">Keine Routen</div>
  return (
    <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 overflow-hidden">
      <table className="w-full text-sm">
        <thead>
          <tr className="text-left text-gray-500 text-xs border-b border-gray-700">
            <th className="px-3 py-2">Ziel</th>
            <th className="px-3 py-2">Gateway</th>
            <th className="px-3 py-2">Flags</th>
            <th className="px-3 py-2">Interface</th>
          </tr>
        </thead>
        <tbody className="divide-y divide-gray-700/50">
          {routes.map((r, i) => (
            <tr key={i}>
              <td className="px-3 py-2 text-white font-mono text-xs">{r.destination}</td>
              <td className="px-3 py-2 text-gray-400 font-mono text-xs">{r.gateway}</td>
              <td className="px-3 py-2 text-gray-400 text-xs">{r.flags}</td>
              <td className="px-3 py-2 text-gray-400 text-xs">{r.interface_name || r.iface}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  )
}

function DHCPTab({ sys }) {
  const [dhcpSearch, setDhcpSearch] = useState('')
  // dhcp can be { server, leases: [...] } or flat dhcp_leases
  const dhcp = sys.dhcp || {}
  const allLeases = dhcp.leases || sys.dhcp_leases || []
  const server = dhcp.server || ''

  const leases = dhcpSearch
    ? allLeases.filter((l) => {
        const q = dhcpSearch.toLowerCase()
        return (l.ip || l.address || '').toLowerCase().includes(q) ||
          (l.mac || l.hwaddr || '').toLowerCase().includes(q) ||
          (l.hostname || '').toLowerCase().includes(q)
      })
    : allLeases

  if (allLeases.length === 0) return <div className="text-gray-500">Keine DHCP Leases</div>
  return (
    <div className="space-y-3">
      <div className="flex items-center gap-3">
        {server && <div className="text-sm text-gray-400">DHCP Server: <span className="text-white">{server.toUpperCase()}</span> — {allLeases.length} Lease(s)</div>}
        <div className="relative flex-1">
          <Search className="absolute left-3 top-2 w-4 h-4 text-gray-500" />
          <input
            type="text"
            placeholder="IP, MAC oder Hostname..."
            value={dhcpSearch}
            onChange={(e) => setDhcpSearch(e.target.value)}
            className="w-full bg-gray-800 border border-gray-700 rounded pl-10 pr-3 py-1.5 text-sm text-white placeholder-gray-600 focus:outline-none focus:border-orange-500"
          />
        </div>
      </div>
      <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 overflow-hidden">
        <table className="w-full text-sm">
          <thead>
            <tr className="text-left text-gray-500 text-xs border-b border-gray-700">
              <th className="px-3 py-2">IP</th>
              <th className="px-3 py-2">MAC</th>
              <th className="px-3 py-2">Hostname</th>
              <th className="px-3 py-2">Status</th>
              <th className="px-3 py-2">Ablauf</th>
            </tr>
          </thead>
          <tbody className="divide-y divide-gray-700/50">
            {leases.map((l, i) => (
              <tr key={i}>
                <td className="px-3 py-2 text-white font-mono text-xs">{l.ip || l.address}</td>
                <td className="px-3 py-2 text-gray-400 font-mono text-xs">{l.mac || l.hwaddr}</td>
                <td className="px-3 py-2 text-gray-400 text-xs">{l.hostname || '—'}</td>
                <td className="px-3 py-2">
                  <span className={`text-xs ${l.status === 'active' ? 'text-green-400' : 'text-gray-500'}`}>
                    {l.status || '—'}
                  </span>
                </td>
                <td className="px-3 py-2 text-gray-400 text-xs">{l.end || l.expires || l.expire || '—'}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  )
}

function CertsTab({ sys }) {
  const certs = sys.certificates || []
  if (certs.length === 0) return <div className="text-gray-500">Keine Zertifikate</div>

  const now = new Date()

  const remaining = (expires) => {
    if (!expires) return null
    const diff = expires - now
    if (diff < 0) return { text: 'Abgelaufen', color: 'text-red-400', bg: 'bg-red-500/10 border-red-500/20', barColor: 'bg-red-500', pct: 0 }
    const days = Math.floor(diff / 86400000)
    if (days > 365) {
      const y = Math.floor(days / 365)
      const m = Math.floor((days % 365) / 30)
      return { text: `${y}J ${m}M`, color: 'text-gray-400', bg: 'bg-gray-800/50 border-gray-700/50', barColor: 'bg-emerald-500', pct: 100 }
    }
    if (days > 7) return { text: `${days} Tage`, color: 'text-gray-400', bg: 'bg-gray-800/50 border-gray-700/50', barColor: 'bg-emerald-500', pct: Math.min(100, days / 3.65) }
    if (days > 0) return { text: `${days} Tage`, color: 'text-yellow-400', bg: 'bg-yellow-500/10 border-yellow-500/20', barColor: 'bg-yellow-500', pct: Math.min(100, days / 3.65) }
    return { text: 'Heute', color: 'text-red-400', bg: 'bg-red-500/10 border-red-500/20', barColor: 'bg-red-500', pct: 0 }
  }

  const sorted = [...certs].sort((a, b) => {
    const ea = a.not_after ? new Date(a.not_after) : new Date('2099-01-01')
    const eb = b.not_after ? new Date(b.not_after) : new Date('2099-01-01')
    return ea - eb
  })

  const expiredCount = sorted.filter(c => c.not_after && new Date(c.not_after) < now).length
  const soonCount = sorted.filter(c => {
    if (!c.not_after) return false
    const e = new Date(c.not_after)
    return e >= now && (e - now) < 7 * 86400000
  }).length

  return (
    <div className="space-y-4">
      {/* Summary */}
      <div className="flex gap-3">
        <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 px-4 py-2 flex-1 text-center">
          <div className="text-2xl font-bold text-white">{sorted.length}</div>
          <div className="text-xs text-gray-500">Gesamt</div>
        </div>
        {expiredCount > 0 && (
          <div className="bg-red-500/10 rounded-lg border border-red-500/30 px-4 py-2 flex-1 text-center">
            <div className="text-2xl font-bold text-red-400">{expiredCount}</div>
            <div className="text-xs text-red-400/70">Abgelaufen</div>
          </div>
        )}
        {soonCount > 0 && (
          <div className="bg-yellow-500/10 rounded-lg border border-yellow-500/30 px-4 py-2 flex-1 text-center">
            <div className="text-2xl font-bold text-yellow-400">{soonCount}</div>
            <div className="text-xs text-yellow-400/70">&lt;7 Tage</div>
          </div>
        )}
      </div>

      {/* Certificate Cards */}
      <div className="space-y-2">
        {sorted.map((c, i) => {
          const expires = c.not_after ? new Date(c.not_after) : null
          const r = remaining(expires)
          const type = c.type || (c.is_ca ? 'CA' : 'Cert')
          return (
            <div key={i} className={`rounded border px-3 py-2 ${r ? r.bg : 'bg-gray-800/50 border-gray-700/50'}`}>
              <div className="flex items-center justify-between gap-2">
                <div className="min-w-0 flex-1 flex items-center gap-2">
                  <span className="text-white text-xs font-medium truncate">{c.name || c.subject || '--'}</span>
                  <span className="text-[9px] px-1 py-0.5 rounded bg-gray-700/50 text-gray-500 shrink-0">{type}</span>
                </div>
                <div className="text-right shrink-0">
                  {r ? (
                    <span className={`text-xs font-medium ${r.color}`}>{r.text}</span>
                  ) : (
                    <span className="text-xs text-gray-600">--</span>
                  )}
                </div>
              </div>
              {r && r.pct !== undefined && (
                <div className="mt-1 h-0.5 bg-gray-700/50 rounded-full overflow-hidden">
                  <div className={`h-full rounded-full ${r.barColor}`} style={{ width: `${r.pct}%` }} />
                </div>
              )}
            </div>
          )
        })}
      </div>
    </div>
  )
}

function PVEBackupsTab({ sys }) {
  const [monthOffset, setMonthOffset] = useState(0)

  const backups = sys?.backups || {}
  const jobs = backups.jobs || []
  const tasks = backups.tasks || []

  // Stats
  const totalJobs = jobs.filter(j => j.enabled === 1 || j.enabled === true).length
  const okTasks = tasks.filter(t => t.status === 'OK').length
  const failedTasks = tasks.filter(t => t.status && t.status !== 'OK').length
  const successRate = tasks.length > 0 ? Math.round((okTasks / tasks.length) * 100) : null

  // Naechster Lauf
  const nextRuns = jobs.map(j => j.next_run).filter(Boolean).sort()
  const nextRun = nextRuns[0] ? new Date(nextRuns[0] * 1000) : null

  // Kalender
  const now = new Date()
  const calMonth = new Date(now.getFullYear(), now.getMonth() + monthOffset, 1)
  const year = calMonth.getFullYear()
  const month = calMonth.getMonth()
  const daysInMonth = new Date(year, month + 1, 0).getDate()
  const firstDayOfWeek = (new Date(year, month, 1).getDay() + 6) % 7 // Mo=0

  // Tasks nach Tag gruppieren
  const tasksByDay = {}
  tasks.forEach(t => {
    const d = new Date(t.starttime * 1000)
    if (d.getFullYear() === year && d.getMonth() === month) {
      const day = d.getDate()
      if (!tasksByDay[day]) tasksByDay[day] = []
      tasksByDay[day].push(t)
    }
  })

  // Geplante Tage (aus Schedule-Pattern)
  const plannedDays = new Set()
  jobs.forEach(j => {
    if (!j.enabled) return
    const nr = j.next_run
    if (nr) {
      const d = new Date(nr * 1000)
      if (d.getFullYear() === year && d.getMonth() === month) {
        plannedDays.add(d.getDate())
      }
    }
  })

  const today = new Date()
  const isCurrentMonth = today.getFullYear() === year && today.getMonth() === month

  const dayNames = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']
  const monthNames = ['Januar', 'Februar', 'Maerz', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember']

  return (
    <div className="space-y-4">
      {/* Stats */}
      <div className="grid grid-cols-4 gap-3">
        <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-3 text-center">
          <div className="text-gray-500 text-xs mb-1">Jobs</div>
          <div className="text-xl font-bold text-white">{totalJobs}</div>
        </div>
        <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-3 text-center">
          <div className="text-gray-500 text-xs mb-1">30 Tage</div>
          <div className="text-xl font-bold text-white">{tasks.length}</div>
        </div>
        <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-3 text-center">
          <div className="text-gray-500 text-xs mb-1">Erfolgsrate</div>
          <div className={`text-xl font-bold ${successRate === 100 ? 'text-emerald-400' : successRate === null ? 'text-gray-500' : successRate >= 90 ? 'text-yellow-400' : 'text-red-400'}`}>
            {successRate !== null ? `${successRate}%` : '--'}
          </div>
        </div>
        <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-3 text-center">
          <div className="text-gray-500 text-xs mb-1">Naechstes</div>
          <div className="text-sm font-bold text-white">
            {nextRun ? nextRun.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit' }) + ', ' + nextRun.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' }) : '--'}
          </div>
        </div>
      </div>

      {/* Kalender */}
      <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-4">
        <div className="flex items-center justify-between mb-4">
          <button onClick={() => setMonthOffset(monthOffset - 1)} className="text-gray-400 hover:text-white px-2 py-1">&lt;</button>
          <h3 className="text-white font-semibold">{monthNames[month]} {year}</h3>
          <button onClick={() => setMonthOffset(monthOffset + 1)} className="text-gray-400 hover:text-white px-2 py-1">&gt;</button>
        </div>

        <div className="grid grid-cols-7 gap-1 text-center">
          {dayNames.map(d => (
            <div key={d} className="text-gray-500 text-xs py-1">{d}</div>
          ))}
          {/* Leere Zellen vor dem 1. */}
          {Array.from({ length: firstDayOfWeek }).map((_, i) => (
            <div key={`empty-${i}`} />
          ))}
          {/* Tage */}
          {Array.from({ length: daysInMonth }).map((_, i) => {
            const day = i + 1
            const dayTasks = tasksByDay[day] || []
            const isToday = isCurrentMonth && day === today.getDate()
            const hasOk = dayTasks.some(t => t.status === 'OK')
            const hasFailed = dayTasks.some(t => t.status && t.status !== 'OK')
            const isPlanned = plannedDays.has(day)

            return (
              <div
                key={day}
                className={`relative py-2 rounded text-sm ${
                  isToday ? 'border border-emerald-500/50' :
                  'border border-transparent'
                } ${hasOk ? 'bg-emerald-900/20' : hasFailed ? 'bg-red-900/20' : ''}`}
              >
                <span className={`${isToday ? 'text-emerald-400 font-bold' : 'text-gray-300'}`}>{day}</span>
                {/* Dot indicators */}
                <div className="flex justify-center gap-0.5 mt-0.5">
                  {hasOk && <span className="w-1.5 h-1.5 rounded-full bg-emerald-400" />}
                  {hasFailed && <span className="w-1.5 h-1.5 rounded-full bg-red-400" />}
                  {isPlanned && !hasOk && !hasFailed && <span className="w-1.5 h-1.5 rounded-full bg-blue-400" />}
                </div>
              </div>
            )
          })}
        </div>

        {/* Legende */}
        <div className="flex items-center gap-4 mt-3 text-xs text-gray-500">
          <span className="flex items-center gap-1"><span className="w-2 h-2 rounded-full bg-emerald-400" /> OK</span>
          <span className="flex items-center gap-1"><span className="w-2 h-2 rounded-full bg-red-400" /> Fehler</span>
          <span className="flex items-center gap-1"><span className="w-2 h-2 rounded-full bg-blue-400" /> Geplant</span>
        </div>
      </div>

      {/* Konfigurierte Jobs */}
      <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-4">
        <h3 className="text-white font-semibold mb-3">Konfigurierte Jobs</h3>
        {jobs.length === 0 ? (
          <div className="text-gray-500 text-sm">Keine Backup-Jobs konfiguriert</div>
        ) : (
          <div className="space-y-2">
            {jobs.map((job, i) => {
              const nr = job.next_run ? new Date(job.next_run * 1000) : null
              const vmids = job.vmid || (job.all ? 'Alle' + (job.exclude ? ` (ohne ${job.exclude})` : '') : '--')
              return (
                <div key={i} className="bg-gray-900 rounded p-3 flex items-center justify-between">
                  <div>
                    <div className="flex items-center gap-2">
                      <span className={`w-2 h-2 rounded-full ${job.enabled ? 'bg-emerald-400' : 'bg-gray-600'}`} />
                      <span className="text-white text-sm font-medium">{vmids}</span>
                    </div>
                    <div className="text-gray-500 text-xs mt-1">
                      {job.schedule} &middot; {job.storage} &middot; {job.mode}
                      {job.node && <span> &middot; Node: {job.node}</span>}
                    </div>
                  </div>
                  {nr && (
                    <div className="text-right text-xs text-gray-400">
                      Naechstes: {nr.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit' })}, {nr.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' })}
                    </div>
                  )}
                </div>
              )
            })}
          </div>
        )}
      </div>

      {/* Letzte Backups */}
      {tasks.length > 0 && (
        <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-4">
          <h3 className="text-white font-semibold mb-3">Letzte Backups ({tasks.length})</h3>
          <div className="space-y-1 max-h-60 overflow-y-auto">
            {tasks.slice(0, 30).map((t, i) => {
              const start = new Date(t.starttime * 1000)
              const duration = t.endtime && t.starttime ? Math.round((t.endtime - t.starttime) / 60) : null
              return (
                <div key={i} className="flex items-center justify-between text-xs py-1 border-b border-gray-800/50">
                  <div className="flex items-center gap-2">
                    <span className={`w-2 h-2 rounded-full ${t.status === 'OK' ? 'bg-emerald-400' : 'bg-red-400'}`} />
                    <span className="text-gray-300">
                      {start.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' })} {start.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' })}
                    </span>
                  </div>
                  <div className="flex items-center gap-3">
                    {duration !== null && <span className="text-gray-500">{duration} min</span>}
                    <span className={`${t.status === 'OK' ? 'text-emerald-400' : 'text-red-400'}`}>{t.status}</span>
                  </div>
                </div>
              )
            })}
          </div>
        </div>
      )}
    </div>
  )
}

function SecurityTab({ sys }) {
  const sec = sys?.security
  if (!sec) return <div className="text-gray-500">Keine Sicherheitsdaten verfuegbar</div>

  const summary = sec.summary || {}
  const logins = sec.ssh_logins || []
  const sessions = sec.sessions || []

  const cards = [
    { label: 'Akzeptiert', value: summary.total_accepted || 0, color: 'text-green-400' },
    { label: 'Abgelehnt', value: summary.total_failed || 0, color: 'text-red-400' },
    { label: 'Eindeutige IPs', value: summary.unique_ips || 0, color: 'text-blue-400' },
    { label: 'Letzter Login', value: summary.last_login ? new Date(summary.last_login).toLocaleString('de-DE') : '-', color: 'text-gray-300', small: true },
  ]

  return (
    <div className="space-y-4">
      {/* Summary Cards */}
      <div className="grid grid-cols-2 md:grid-cols-4 gap-3">
        {cards.map((c, i) => (
          <div key={i} className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-3">
            <div className="text-gray-500 text-xs mb-1">{c.label}</div>
            <div className={`${c.small ? 'text-sm' : 'text-xl font-bold'} ${c.color}`}>{c.value}</div>
          </div>
        ))}
      </div>

      {/* SSH Logins */}
      <div>
        <h3 className="text-sm font-medium text-gray-400 mb-2">SSH-Logins</h3>
        {logins.length === 0 ? (
          <div className="text-gray-500 text-sm">Keine SSH-Login-Events</div>
        ) : (
          <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 overflow-hidden">
            <table className="w-full text-xs">
              <thead>
                <tr className="text-left text-gray-500 border-b border-gray-700">
                  <th className="px-3 py-2">Zeitstempel</th>
                  <th className="px-3 py-2">User</th>
                  <th className="px-3 py-2">Quell-IP</th>
                  <th className="px-3 py-2">Port</th>
                  <th className="px-3 py-2">Methode</th>
                  <th className="px-3 py-2">Status</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-gray-700/50">
                {logins.map((e, i) => (
                  <tr key={i}>
                    <td className="px-3 py-1.5 text-gray-400">{e.timestamp ? new Date(e.timestamp).toLocaleString('de-DE') : '-'}</td>
                    <td className="px-3 py-1.5 text-white">{e.user}</td>
                    <td className="px-3 py-1.5 text-gray-300 font-mono">{e.source}</td>
                    <td className="px-3 py-1.5 text-gray-400">{e.port}</td>
                    <td className="px-3 py-1.5">
                      <span className="px-1.5 py-0.5 bg-gray-700 rounded text-gray-400 text-xs">{e.method}</span>
                    </td>
                    <td className="px-3 py-1.5">
                      <span className="flex items-center gap-1.5">
                        <span className={`w-1.5 h-1.5 rounded-full ${e.status === 'accepted' ? 'bg-green-400' : 'bg-red-400'}`} />
                        <span className={e.status === 'accepted' ? 'text-green-400' : 'text-red-400'}>{e.status}</span>
                      </span>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>

      {/* Sessions */}
      <div>
        <h3 className="text-sm font-medium text-gray-400 mb-2">Sessions</h3>
        {sessions.length === 0 ? (
          <div className="text-gray-500 text-sm">Keine Sessions</div>
        ) : (
          <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 overflow-hidden">
            <table className="w-full text-xs">
              <thead>
                <tr className="text-left text-gray-500 border-b border-gray-700">
                  <th className="px-3 py-2">User</th>
                  <th className="px-3 py-2">TTY</th>
                  <th className="px-3 py-2">Von</th>
                  <th className="px-3 py-2">Login</th>
                  <th className="px-3 py-2">Logout</th>
                  <th className="px-3 py-2">Dauer</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-gray-700/50">
                {sessions.map((s, i) => (
                  <tr key={i}>
                    <td className="px-3 py-1.5 text-white">{s.user}</td>
                    <td className="px-3 py-1.5 text-gray-400 font-mono">{s.tty}</td>
                    <td className="px-3 py-1.5 text-gray-300 font-mono">{s.from || '-'}</td>
                    <td className="px-3 py-1.5 text-gray-400">{s.login}</td>
                    <td className="px-3 py-1.5 text-gray-400">{s.logout || '-'}</td>
                    <td className="px-3 py-1.5 text-gray-400">{s.duration || '-'}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>
    </div>
  )
}

function TasksTab({ agentId, agentName, platform }) {
  const [tasks, setTasks] = useState([])
  const [total, setTotal] = useState(0)
  const [loading, setLoading] = useState(true)
  const [showDialog, setShowDialog] = useState(false)
  const [editTask, setEditTask] = useState(null)
  const [creating, setCreating] = useState(false)
  const [error, setError] = useState('')
  const [showWebhook, setShowWebhook] = useState(false)
  const isLinux = platform === 'linux'

  const defaultForm = {
    name: '', action: isLinux ? 'update' : 'backup', schedule_type: 'once', schedule_time: '02:00',
    scheduled_at: '', schedule_weekday: 1, schedule_monthday: 1,
    reboot: false, health_check: false, health_check_timeout: 600,
    security_only: false,
    webhook_url: '', active: true,
  }

  const jobTemplatesFreeBSD = [
    {
      label: 'Wöchentliches Update',
      form: { name: 'Wöchentliches Update', action: 'update', schedule_type: 'weekly',
        schedule_time: '02:00', schedule_weekday: 0, reboot: true, health_check: true,
        health_check_timeout: 600, active: true },
    },
    {
      label: 'Monatliches Update',
      form: { name: 'Monatliches Update', action: 'update', schedule_type: 'monthly',
        schedule_time: '02:00', schedule_monthday: 1, reboot: true, health_check: true,
        health_check_timeout: 600, active: true },
    },
    {
      label: 'Tägliches Backup',
      form: { name: 'Tägliches Backup', action: 'backup', schedule_type: 'daily',
        schedule_time: '03:00', reboot: false, health_check: false, active: true },
    },
    {
      label: 'Monatliches Backup',
      form: { name: 'Monatliches Backup', action: 'backup', schedule_type: 'monthly',
        schedule_time: '03:00', schedule_monthday: 1, reboot: false, health_check: false, active: true },
    },
    {
      label: 'Update + ERP-Webhook',
      form: { name: 'Monatliches Update + Servicebericht', action: 'update', schedule_type: 'monthly',
        schedule_time: '02:00', schedule_monthday: 1, reboot: true, health_check: true,
        health_check_timeout: 600, active: true },
      showWebhook: true,
    },
  ]

  const jobTemplatesLinux = [
    {
      label: 'Wöchentlich alle Updates',
      form: { name: 'Wöchentliches Debian-Update', action: 'update', schedule_type: 'weekly',
        schedule_time: '02:00', schedule_weekday: 0, reboot: true, health_check: true,
        health_check_timeout: 600, security_only: false, active: true },
    },
    {
      label: 'Monatlich alle Updates',
      form: { name: 'Monatliches Debian-Update', action: 'update', schedule_type: 'monthly',
        schedule_time: '02:00', schedule_monthday: 1, reboot: true, health_check: true,
        health_check_timeout: 600, security_only: false, active: true },
    },
    {
      label: 'Wöchentlich nur Security',
      form: { name: 'Wöchentliche Security-Updates', action: 'update', schedule_type: 'weekly',
        schedule_time: '03:00', schedule_weekday: 3, reboot: false, health_check: true,
        health_check_timeout: 300, security_only: true, active: true },
    },
    {
      label: 'Täglich Security (kein Reboot)',
      form: { name: 'Tägliche Security-Updates', action: 'update', schedule_type: 'daily',
        schedule_time: '04:00', reboot: false, health_check: false,
        security_only: true, active: true },
    },
    {
      label: 'Update + Webhook',
      form: { name: 'Monatliches Update + Servicebericht', action: 'update', schedule_type: 'monthly',
        schedule_time: '02:00', schedule_monthday: 1, reboot: true, health_check: true,
        health_check_timeout: 600, security_only: false, active: true },
      showWebhook: true,
    },
  ]

  const jobTemplates = isLinux ? jobTemplatesLinux : jobTemplatesFreeBSD
  const [form, setForm] = useState(defaultForm)

  const loadTasks = () => {
    api.getTasks({ agent_id: agentId, limit: 50 })
      .then(resp => { setTasks(resp.data || []); setTotal(resp.total || 0) })
      .catch(() => setTasks([]))
      .finally(() => setLoading(false))
  }

  useEffect(() => { loadTasks() }, [agentId])
  useEffect(() => { const iv = setInterval(loadTasks, 15000); return () => clearInterval(iv) }, [agentId])

  const handleCreate = async () => {
    setCreating(true); setError('')
    try {
      const data = { agent_id: agentId, name: form.name, action: form.action, schedule_type: form.schedule_type, schedule_time: form.schedule_time, active: form.active }
      if (form.schedule_type === 'once' && form.scheduled_at) {
        data.scheduled_at = new Date(form.scheduled_at).toISOString()
      }
      if (form.schedule_type === 'weekly') data.schedule_weekday = parseInt(form.schedule_weekday)
      if (form.schedule_type === 'monthly') data.schedule_monthday = parseInt(form.schedule_monthday)
      if (form.action === 'update') {
        data.reboot = form.reboot; data.health_check = form.health_check
        if (form.health_check) data.health_check_timeout = parseInt(form.health_check_timeout) || 600
        if (isLinux) data.security_only = form.security_only || false
      }
      if (form.webhook_url) data.webhook_url = form.webhook_url
      await api.createTask(data)
      setShowDialog(false); setForm(defaultForm); setShowWebhook(false); loadTasks()
    } catch (e) { setError(e.message) } finally { setCreating(false) }
  }

  const handleToggle = async (id) => {
    try { await api.toggleTask(id); loadTasks() } catch (e) { setError(e.message) }
  }
  const handleDelete = async (id) => {
    if (!confirm('Job wirklich loeschen?')) return
    try { await api.deleteTask(id); loadTasks() } catch (e) { setError(e.message) }
  }
  const handleEdit = (t) => {
    setEditTask(t)
    setForm({
      name: t.name || '',
      action: t.action,
      schedule_type: t.schedule_type || 'once',
      schedule_time: t.schedule_time || '02:00',
      scheduled_at: '',
      schedule_weekday: t.schedule_weekday ?? 1,
      schedule_monthday: t.schedule_monthday ?? 1,
      reboot: t.reboot || false,
      health_check: t.health_check || false,
      health_check_timeout: t.health_check_timeout || 600,
      webhook_url: t.webhook_url || '',
      active: t.active !== false,
    })
    setShowWebhook(!!t.webhook_url)
    setShowDialog(true)
  }

  const handleSave = async () => {
    setCreating(true); setError('')
    try {
      const data = {
        name: form.name, schedule_type: form.schedule_type, schedule_time: form.schedule_time,
        active: form.active, reboot: form.reboot, health_check: form.health_check,
        health_check_timeout: parseInt(form.health_check_timeout) || 600,
        webhook_url: form.webhook_url,
      }
      if (form.schedule_type === 'weekly') data.schedule_weekday = parseInt(form.schedule_weekday)
      if (form.schedule_type === 'monthly') data.schedule_monthday = parseInt(form.schedule_monthday)
      await api.updateTask(editTask.id, data)
      setShowDialog(false); setEditTask(null); setForm(defaultForm); setShowWebhook(false); loadTasks()
    } catch (e) { setError(e.message) } finally { setCreating(false) }
  }

  const handleRunNow = async (id) => {
    try {
      await api.runTaskNow(id)
      setTimeout(loadTasks, 1500)
    } catch (e) { setError(e.message) }
  }

  const weekdays = ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa']

  const fmtInterval = (t) => {
    if (t.schedule_type === 'daily') return `Täglich ${t.schedule_time}`
    if (t.schedule_type === 'weekly') return `Wöchentlich ${weekdays[t.schedule_weekday || 0]} ${t.schedule_time}`
    if (t.schedule_type === 'monthly') return `Monatlich ${t.schedule_monthday || 1}. ${t.schedule_time}`
    return 'Einmalig'
  }

  const fmtDate = (d) => d ? new Date(d).toLocaleString('de-DE', { day: '2-digit', month: '2-digit', year: '2-digit', hour: '2-digit', minute: '2-digit' }) : '—'

  const inputCls = 'w-full bg-gray-700 border border-gray-600 rounded px-3 py-2 text-sm text-white focus:outline-none focus:border-orange-500'
  const labelCls = 'block text-xs text-gray-400 mb-1'

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between">
        <div className="text-sm text-gray-400">{total} Job(s)</div>
        <button onClick={() => setShowDialog(true)} className="flex items-center gap-1.5 px-3 py-1.5 bg-orange-600 hover:bg-orange-700 rounded text-sm text-white transition-colors">
          <Plus className="w-4 h-4" /> Neuer Job
        </button>
      </div>

      {/* Modal */}
      {showDialog && (
        <div className="fixed inset-0 bg-black/60 z-50 flex items-center justify-center" onClick={() => setShowDialog(false)}>
          <div className="bg-gray-800 rounded-lg border border-gray-700 w-full max-w-lg mx-4 max-h-[90vh] overflow-y-auto" onClick={e => e.stopPropagation()}>
            <div className="flex items-center justify-between px-5 py-4 border-b border-gray-700">
              <h3 className="text-white font-semibold">{editTask ? `Job bearbeiten — ${editTask.name || `#${editTask.id}`}` : `Neuer Job${agentName ? ` — ${agentName}` : ''}`}</h3>
              <button onClick={() => { setShowDialog(false); setEditTask(null) }} className="text-gray-400 hover:text-white"><X className="w-5 h-5" /></button>
            </div>
            {!editTask && (
              <div className="px-5 pt-4 pb-2 border-b border-gray-700/50">
                <p className="text-xs text-gray-500 mb-2">Vorlage wählen</p>
                <div className="flex flex-wrap gap-2">
                  {jobTemplates.map((tpl, i) => (
                    <button key={i} onClick={() => {
                      setForm({ ...defaultForm, ...tpl.form, scheduled_at: '', schedule_weekday: tpl.form.schedule_weekday ?? 1, schedule_monthday: tpl.form.schedule_monthday ?? 1 })
                      setShowWebhook(!!tpl.showWebhook)
                    }} className="px-3 py-1.5 bg-gray-700 hover:bg-gray-600 rounded text-xs text-gray-300 hover:text-white transition-colors">
                      {tpl.label}
                    </button>
                  ))}
                </div>
              </div>
            )}
            <div className="px-5 py-4 space-y-4">
              <div>
                <label className={labelCls}>Name *</label>
                <input type="text" value={form.name} onChange={e => setForm({...form, name: e.target.value})} placeholder="z.B. Monatliches Update" className={inputCls} />
              </div>
              <div className="grid grid-cols-2 gap-3">
                <div>
                  <label className={labelCls}>Intervall *</label>
                  <select value={form.schedule_type} onChange={e => setForm({...form, schedule_type: e.target.value})} className={inputCls} disabled={!!editTask}>
                    <option value="once">Einmalig</option>
                    <option value="daily">Täglich</option>
                    <option value="weekly">Wöchentlich</option>
                    <option value="monthly">Monatlich</option>
                  </select>
                </div>
                <div>
                  <label className={labelCls}>Uhrzeit *</label>
                  <input type="time" value={form.schedule_time} onChange={e => setForm({...form, schedule_time: e.target.value})} className={inputCls} />
                </div>
              </div>
              {form.schedule_type === 'once' && (
                <div>
                  <label className={labelCls}>Datum</label>
                  <input type="datetime-local" value={form.scheduled_at} onChange={e => setForm({...form, scheduled_at: e.target.value})} className={inputCls} />
                </div>
              )}
              {form.schedule_type === 'weekly' && (
                <div>
                  <label className={labelCls}>Wochentag</label>
                  <select value={form.schedule_weekday} onChange={e => setForm({...form, schedule_weekday: e.target.value})} className={inputCls}>
                    {weekdays.map((d, i) => <option key={i} value={i}>{d}</option>)}
                  </select>
                </div>
              )}
              {form.schedule_type === 'monthly' && (
                <div>
                  <label className={labelCls}>Tag im Monat</label>
                  <input type="number" min="1" max="28" value={form.schedule_monthday} onChange={e => setForm({...form, schedule_monthday: e.target.value})} className={inputCls} />
                </div>
              )}
              {!editTask && (
                <div>
                  <label className={labelCls}>Aktion *</label>
                  <div className="flex gap-2">
                    {(isLinux ? ['update'] : ['backup', 'update']).map(a => (
                      <button key={a} onClick={() => setForm({...form, action: a})}
                        className={`flex-1 py-2 rounded text-sm font-medium transition-colors ${form.action === a ? 'bg-orange-600 text-white' : 'bg-gray-700 text-gray-400 hover:bg-gray-600'}`}>
                        {a === 'backup' ? 'Backup' : 'apt-get upgrade'}
                      </button>
                    ))}
                  </div>
                </div>
              )}
              {form.action === 'update' && (
                <div className="space-y-2 pl-1">
                  {isLinux && (
                    <label className="flex items-center gap-2 text-sm text-gray-300 cursor-pointer">
                      <input type="checkbox" checked={form.security_only || false} onChange={e => setForm({...form, security_only: e.target.checked})} className="accent-orange-500" />
                      Nur Security-Updates (apt-get upgrade mit security-Filter)
                    </label>
                  )}
                  <label className="flex items-center gap-2 text-sm text-gray-300 cursor-pointer">
                    <input type="checkbox" checked={form.reboot} onChange={e => setForm({...form, reboot: e.target.checked})} className="accent-orange-500" />
                    Reboot nach Update
                  </label>
                  <label className="flex items-center gap-2 text-sm text-gray-300 cursor-pointer">
                    <input type="checkbox" checked={form.health_check} onChange={e => setForm({...form, health_check: e.target.checked})} className="accent-orange-500" />
                    Health-Check nach Update
                  </label>
                  {form.health_check && (
                    <div className="pl-6">
                      <label className={labelCls}>Health-Check Timeout (Sekunden)</label>
                      <input type="number" value={form.health_check_timeout} onChange={e => setForm({...form, health_check_timeout: e.target.value})} className={inputCls + ' max-w-[200px]'} />
                    </div>
                  )}
                </div>
              )}
              <div>
                <button onClick={() => setShowWebhook(!showWebhook)} className="flex items-center gap-1 text-xs text-gray-400 hover:text-gray-300">
                  {showWebhook ? <ChevronDown className="w-3.5 h-3.5" /> : <ChevronRight className="w-3.5 h-3.5" />} Webhook-URL (optional)
                </button>
                {showWebhook && (
                  <div>
                    <input type="text" value={form.webhook_url} onChange={e => setForm({...form, webhook_url: e.target.value})} placeholder="https://erp.example.com/api/service-reports" className={inputCls + ' mt-1'} />
                    <p className="text-xs text-gray-500 mt-1">Empfangt: customer_id, hostname, opnsense_version, reachable, update_status</p>
                  </div>
                )}
              </div>
              <label className="flex items-center gap-2 text-sm text-gray-300 cursor-pointer">
                <input type="checkbox" checked={form.active} onChange={e => setForm({...form, active: e.target.checked})} className="accent-orange-500" />
                Job ist aktiv
              </label>
              {error && <div className="text-sm text-red-400">{error}</div>}
            </div>
            <div className="flex justify-end gap-2 px-5 py-4 border-t border-gray-700">
              <button onClick={() => { setShowDialog(false); setEditTask(null); setError('') }} className="px-4 py-2 bg-gray-700 hover:bg-gray-600 rounded text-sm text-gray-300 transition-colors">Abbrechen</button>
              <button onClick={editTask ? handleSave : handleCreate} disabled={creating || !form.name} className="px-4 py-2 bg-orange-600 hover:bg-orange-700 disabled:bg-gray-700 disabled:text-gray-500 rounded text-sm text-white transition-colors">
                {creating ? (editTask ? 'Speichere...' : 'Erstelle...') : (editTask ? 'Speichern' : 'Erstellen')}
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Table */}
      {loading ? (
        <div className="text-gray-500">Laden...</div>
      ) : tasks.length === 0 ? (
        <div className="text-gray-500 bg-gray-800/30 rounded-lg border border-gray-800 px-4 py-6 text-center text-sm">Keine Jobs vorhanden</div>
      ) : (
        <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 overflow-hidden">
          <table className="w-full text-sm">
            <thead>
              <tr className="text-left text-gray-500 text-xs border-b border-gray-700">
                <th className="px-3 py-2 w-8">Status</th>
                <th className="px-3 py-2">Name</th>
                <th className="px-3 py-2">Aktion</th>
                <th className="px-3 py-2">Intervall</th>
                <th className="px-3 py-2">Nächster Lauf</th>
                <th className="px-3 py-2">Letzter Lauf</th>
                <th className="px-3 py-2">Webhook</th>
                <th className="px-3 py-2 text-right">Aktionen</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-gray-700/50">
              {tasks.map(t => (
                <tr key={t.id} className={!t.active ? 'opacity-50' : ''}>
                  <td className="px-3 py-2">
                    <div className="flex items-center gap-1.5">
                      <span className={`inline-block w-2 h-2 rounded-full flex-shrink-0 ${t.active ? 'bg-green-500' : 'bg-gray-500'}`} title={t.active ? 'Aktiv' : 'Inaktiv'} />
                      {t.status === 'running' && <span className="text-xs px-1.5 py-0.5 rounded bg-blue-900/50 text-blue-300">lauft</span>}
                      {t.status === 'failed' && <span className="text-xs px-1.5 py-0.5 rounded bg-red-900/50 text-red-300">fehler</span>}
                      {t.status === 'completed_with_warning' && <span className="text-xs px-1.5 py-0.5 rounded bg-yellow-900/50 text-yellow-300" title="Update OK, aber Agent nicht wieder online">warnung</span>}
                      {t.status === 'cancelled' && <span className="text-xs px-1.5 py-0.5 rounded bg-gray-700 text-gray-400">abgebr.</span>}
                    </div>
                  </td>
                  <td className="px-3 py-2 text-white">{t.name || `Job #${t.id}`}</td>
                  <td className="px-3 py-2 text-gray-300 capitalize">{t.action}</td>
                  <td className="px-3 py-2 text-gray-400 text-xs">{fmtInterval(t)}</td>
                  <td className="px-3 py-2 text-gray-400 text-xs">{fmtDate(t.next_run)}</td>
                  <td className="px-3 py-2 text-gray-400 text-xs">{fmtDate(t.last_run)}</td>
                  <td className="px-3 py-2 text-xs">
                    {t.webhook_url ? (
                      t.webhook_sent
                        ? <span className="text-green-400" title={t.webhook_response || 'Gesendet'}>OK</span>
                        : t.last_run
                          ? <span className="text-red-400" title={t.webhook_response || 'Fehlgeschlagen'}>Fehler</span>
                          : <span className="text-gray-500">—</span>
                    ) : <span className="text-gray-600">—</span>}
                  </td>
                  <td className="px-3 py-2 text-right">
                    <div className="flex items-center justify-end gap-1">
                      <button onClick={() => handleEdit(t)} className="text-gray-400 hover:text-white p-1 rounded hover:bg-gray-700 transition-colors" title="Bearbeiten">
                        <Pencil className="w-4 h-4" />
                      </button>
                      <button onClick={() => handleRunNow(t.id)} className="text-blue-400 hover:text-blue-300 p-1 rounded hover:bg-blue-900/30 transition-colors" title="Jetzt ausführen" disabled={t.status === 'running'}>
                        <Play className="w-4 h-4" />
                      </button>
                      <button onClick={() => handleToggle(t.id)} className={`p-1 rounded transition-colors ${t.active ? 'text-green-400 hover:text-green-300 hover:bg-green-900/30' : 'text-gray-500 hover:text-gray-300 hover:bg-gray-700'}`} title={t.active ? 'Deaktivieren' : 'Aktivieren'}>
                        <Power className="w-4 h-4" />
                      </button>
                      <button onClick={() => handleDelete(t.id)} className="text-red-400 hover:text-red-300 p-1 rounded hover:bg-red-900/30 transition-colors" title="Löschen">
                        <Trash2 className="w-4 h-4" />
                      </button>
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  )
}

function BackupsTab({ agentId }) {
  const [backups, setBackups] = useState([])
  const [loading, setLoading] = useState(true)
  const [creating, setCreating] = useState(false)
  const [msg, setMsg] = useState('')

  const loadBackups = () => {
    api.getBackups(agentId)
      .then((resp) => {
        const list = Array.isArray(resp) ? resp : (resp?.data || resp?.backups || [])
        setBackups(Array.isArray(list) ? list : [])
      })
      .catch(() => setBackups([]))
      .finally(() => setLoading(false))
  }

  useEffect(() => { loadBackups() }, [agentId])

  const triggerBackup = async () => {
    setCreating(true)
    setMsg('')
    try {
      const resp = await api.triggerBackup(agentId)
      const data = resp?.data || resp
      if (data?.new === false) {
        setMsg('Config unveraendert (Hash identisch)')
      } else {
        setMsg('Backup erstellt')
      }
      setTimeout(loadBackups, 1000)
    } catch (e) {
      setMsg('Fehler: ' + e.message)
    } finally {
      setCreating(false)
    }
  }

  if (loading) return <div className="text-gray-500">Laden...</div>
  return (
    <div className="space-y-3">
      <div className="flex items-center gap-3">
        <button
          onClick={triggerBackup}
          disabled={creating}
          className="flex items-center gap-1.5 px-3 py-1.5 bg-orange-600 hover:bg-orange-700 disabled:bg-orange-800 disabled:opacity-50 rounded text-sm text-white transition-colors"
        >
          <Download className="w-4 h-4" />
          {creating ? 'Erstelle...' : 'Backup jetzt erstellen'}
        </button>
        {msg && <span className={`text-sm ${msg.startsWith('Fehler') ? 'text-red-400' : 'text-gray-400'}`}>{msg}</span>}
      </div>
      {backups.length === 0 ? (
        <div className="text-gray-500">Keine Backups vorhanden</div>
      ) : (
        <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 overflow-hidden">
          <table className="w-full text-sm">
            <thead>
              <tr className="text-left text-gray-500 text-xs border-b border-gray-700">
                <th className="px-3 py-2">ID</th>
                <th className="px-3 py-2">Erstellt</th>
                <th className="px-3 py-2">Groesse</th>
                <th className="px-3 py-2">Hash</th>
                <th className="px-3 py-2 text-right">Aktionen</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-gray-700/50">
              {backups.map((b) => (
                <tr key={b.id}>
                  <td className="px-3 py-2 text-white">{b.id}</td>
                  <td className="px-3 py-2 text-gray-400 text-xs">{new Date(b.created_at).toLocaleString('de-DE')}</td>
                  <td className="px-3 py-2 text-gray-400">{formatBytes(b.size)}</td>
                  <td className="px-3 py-2 text-gray-500 font-mono text-xs">{(b.hash || '').substring(0, 16)}...</td>
                  <td className="px-3 py-2 text-right">
                    <button
                      onClick={() => api.downloadBackup(agentId, b.id)}
                      className="text-orange-400 hover:text-orange-300 p-1 rounded hover:bg-orange-900/30 transition-colors"
                      title="config.xml herunterladen"
                    >
                      <Download className="w-4 h-4" />
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  )
}

function LinuxUpdatesTab({ sys, agentId }) {
  const [filter, setFilter] = useState('all')
  const [search, setSearch] = useState('')
  const [running, setRunning] = useState(false)
  const [runResult, setRunResult] = useState(null)

  const updates = sys?.updates?.updates || []
  const secCount = updates.filter(u => u.security).length
  const regCount = updates.length - secCount

  const visible = updates.filter(u => {
    if (filter === 'security' && !u.security) return false
    if (filter === 'regular' && u.security) return false
    if (search) {
      const q = search.toLowerCase()
      return u.package?.toLowerCase().includes(q) || u.repository?.toLowerCase().includes(q)
    }
    return true
  })

  const runUpdate = async () => {
    if (!confirm('Alle Updates jetzt installieren?')) return
    setRunning(true)
    setRunResult(null)
    try {
      const res = await api.runUpdate(agentId, false)
      setRunResult(res.data || res)
    } catch (err) {
      setRunResult({ error: err.message })
    } finally {
      setRunning(false)
    }
  }

  if (updates.length === 0) {
    return (
      <div className="space-y-4">
        <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-6 text-center">
          <div className="w-10 h-10 rounded-full bg-emerald-900/40 flex items-center justify-center mx-auto mb-3">
            <Download className="w-5 h-5 text-emerald-400" />
          </div>
          <p className="text-emerald-400 font-medium text-sm">System ist aktuell</p>
          <p className="text-gray-500 text-xs mt-1">Keine ausstehenden Updates</p>
        </div>
      </div>
    )
  }

  return (
    <div className="space-y-4">
      {/* Header */}
      <div className="flex items-center gap-3 flex-wrap">
        <h3 className="text-white font-semibold">Verfügbare Updates</h3>
        {secCount > 0 && (
          <span className="flex items-center gap-1 bg-red-900/50 border border-red-700/50 text-red-300 text-xs font-semibold px-2.5 py-1 rounded">
            <Shield className="w-3 h-3" /> {secCount} Security
          </span>
        )}
        <span className={`text-xs font-semibold px-2.5 py-1 rounded border ${regCount > 0 ? 'bg-emerald-900/40 border-emerald-700/50 text-emerald-300' : 'bg-gray-700/50 border-gray-600/50 text-gray-400'}`}>
          {regCount} Regular
        </span>
        <div className="ml-auto flex items-center gap-2">
          <button
            onClick={runUpdate}
            disabled={running}
            className="flex items-center gap-1.5 bg-orange-600 hover:bg-orange-500 disabled:bg-gray-700 disabled:text-gray-500 text-white text-xs px-3 py-1.5 rounded transition-colors"
          >
            <Download className="w-3.5 h-3.5" />
            {running ? 'Läuft...' : 'Updates installieren'}
          </button>
        </div>
      </div>

      {/* Filter + Suche */}
      <div className="flex items-center gap-2 flex-wrap">
        {[
          { id: 'all', label: `Alle (${updates.length})` },
          { id: 'security', label: `Security (${secCount})` },
          { id: 'regular', label: `Regular (${regCount})` },
        ].map(f => (
          <button
            key={f.id}
            onClick={() => setFilter(f.id)}
            className={`text-xs px-3 py-1.5 rounded transition-colors border ${
              filter === f.id
                ? 'bg-blue-600 border-blue-500 text-white'
                : 'bg-gray-800 border-gray-700 text-gray-400 hover:bg-gray-700'
            }`}
          >
            {f.label}
          </button>
        ))}
        <div className="ml-auto flex items-center gap-2 bg-gray-800 border border-gray-700 rounded px-2 py-1">
          <Search className="w-3.5 h-3.5 text-gray-500" />
          <input
            type="text"
            placeholder="Suchen..."
            value={search}
            onChange={e => setSearch(e.target.value)}
            className="bg-transparent text-xs text-gray-300 outline-none w-40 placeholder-gray-600"
          />
        </div>
      </div>

      {/* Tabelle */}
      <div className="bg-gray-900/60 rounded-lg border border-gray-700/50 overflow-hidden">
        <table className="w-full text-xs">
          <thead>
            <tr className="border-b border-gray-700/70 text-gray-500 uppercase tracking-wide">
              <th className="text-left px-4 py-2.5">Paket</th>
              <th className="text-left px-4 py-2.5">Aktuelle Version</th>
              <th className="text-left px-4 py-2.5">Neue Version</th>
              <th className="text-left px-4 py-2.5">Repository</th>
            </tr>
          </thead>
          <tbody>
            {visible.map((pkg, i) => (
              <tr
                key={i}
                className={`border-b border-gray-800/50 last:border-0 ${pkg.security ? 'bg-red-950/10' : ''}`}
              >
                <td className="px-4 py-2">
                  <div className="flex items-center gap-2">
                    {pkg.security && <Shield className="w-3.5 h-3.5 text-red-400 flex-shrink-0" />}
                    <span className="font-mono text-gray-200">{pkg.package}</span>
                    {pkg.security && (
                      <span className="text-[10px] font-bold px-1.5 py-0.5 rounded bg-red-900/60 border border-red-700/50 text-red-300">SEC</span>
                    )}
                    {pkg.arch && (
                      <span className="text-[10px] px-1.5 py-0.5 rounded bg-gray-700/60 text-gray-400">{pkg.arch}</span>
                    )}
                  </div>
                </td>
                <td className="px-4 py-2 text-gray-500 font-mono">{pkg.current_version || '—'}</td>
                <td className="px-4 py-2 font-mono">
                  <span className="text-gray-400">→ </span>
                  <span className="text-emerald-400">{pkg.new_version}</span>
                </td>
                <td className="px-4 py-2 text-gray-500">{pkg.repository || '—'}</td>
              </tr>
            ))}
            {visible.length === 0 && (
              <tr>
                <td colSpan={4} className="px-4 py-6 text-center text-gray-600">Keine Pakete gefunden</td>
              </tr>
            )}
          </tbody>
        </table>
      </div>

      {/* Ergebnis */}
      {runResult && (
        <div className={`text-xs p-3 rounded border ${runResult.error ? 'bg-red-900/20 border-red-700/50 text-red-300' : 'bg-gray-800 border-gray-700 text-gray-300'}`}>
          {runResult.error ? runResult.error : (runResult.output || runResult.message || JSON.stringify(runResult))}
        </div>
      )}
    </div>
  )
}

function UpdatesTab({ agentId }) {
  const [checking, setChecking] = useState(false)
  const [updating, setUpdating] = useState(false)
  const [result, setResult] = useState(null)
  const [updateResult, setUpdateResult] = useState(null)
  const [reboot, setReboot] = useState(false)
  const [majorVer, setMajorVer] = useState('')
  const [majorPhase, setMajorPhase] = useState('1')
  const [majorReboot, setMajorReboot] = useState(true)

  const checkUpdates = async () => {
    setChecking(true)
    setResult(null)
    try {
      const res = await api.checkUpdates(agentId)
      setResult(res.data || res)
    } catch (err) {
      setResult({ error: err.message })
    } finally {
      setChecking(false)
    }
  }

  const runUpdate = async () => {
    if (!confirm('Update jetzt ausfuehren?' + (reboot ? ' (mit Reboot)' : ''))) return
    setUpdating(true)
    setUpdateResult(null)
    try {
      const res = await api.runUpdate(agentId, reboot)
      setUpdateResult(res.data || res)
    } catch (err) {
      setUpdateResult({ error: err.message })
    } finally {
      setUpdating(false)
    }
  }

  const runMajorUpdate = async () => {
    if (!majorVer) return
    const phaseText = majorPhase === '1' ? 'Phase 1: Base+Kernel installieren' + (majorReboot ? ' + Reboot' : '') : 'Phase 2: Packages aktualisieren'
    if (!confirm(`Major-Update auf ${majorVer}?\n${phaseText}`)) return
    setUpdating(true)
    setUpdateResult(null)
    try {
      const res = await api.post(`/api/v1/agents/${agentId}/major-update`, {
        version: majorVer,
        phase: majorPhase,
        reboot: majorReboot
      })
      setUpdateResult(res.data || res)
    } catch (err) {
      setUpdateResult({ error: err.message })
    } finally {
      setUpdating(false)
    }
  }

  const runReboot = async () => {
    if (!confirm('Geraet jetzt neu starten?')) return
    try {
      await api.post(`/api/v1/agents/${agentId}/reboot`, { delay: 5 })
      setUpdateResult({ message: 'Reboot in 5 Sekunden...' })
    } catch (err) {
      setUpdateResult({ error: err.message })
    }
  }

  const pendingPkgs = result?.pending_packages || []

  return (
    <div className="space-y-4">
      {/* Update Check */}
      <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-4">
        <div className="flex items-center justify-between mb-3">
          <h3 className="text-white font-semibold">Update-Check</h3>
          <button
            onClick={checkUpdates}
            disabled={checking}
            className="flex items-center gap-2 bg-orange-600 hover:bg-orange-500 disabled:bg-gray-700 disabled:text-gray-500 text-white px-3 py-1.5 rounded text-sm transition-colors"
          >
            <Search className="w-4 h-4" />
            {checking ? 'Pruefe...' : 'Updates pruefen'}
          </button>
        </div>

        {result?.error && (
          <div className="text-red-400 text-sm bg-red-900/20 rounded p-2">{result.error}</div>
        )}

        {result && !result.error && (
          <div className="space-y-3">
            {/* Core Update */}
            <div className="flex items-center gap-3">
              <div className={`w-2.5 h-2.5 rounded-full ${result.core_update_available ? 'bg-orange-400' : 'bg-emerald-400'}`} />
              <span className="text-sm text-gray-300">
                {result.core_update_available ? 'Core-Update verfuegbar' : 'Core ist aktuell'}
              </span>
            </div>
            {result.core_update_info && result.core_update_available && (
              <pre className="bg-gray-900 text-gray-400 text-xs p-2 rounded overflow-x-auto max-h-32">{result.core_update_info}</pre>
            )}

            {/* Reboot Required */}
            {result.reboot_required && (
              <div className="flex items-center gap-3">
                <div className="w-2.5 h-2.5 rounded-full bg-red-400" />
                <span className="text-sm text-red-400 font-medium">Reboot erforderlich</span>
                <button onClick={runReboot} className="ml-auto text-xs bg-red-600 hover:bg-red-500 text-white px-2 py-1 rounded">
                  Jetzt neustarten
                </button>
              </div>
            )}

            {/* Package Updates */}
            <div className="flex items-center gap-3">
              <div className={`w-2.5 h-2.5 rounded-full ${pendingPkgs.length > 0 ? 'bg-orange-400' : 'bg-emerald-400'}`} />
              <span className="text-sm text-gray-300">
                {pendingPkgs.length > 0 ? `${pendingPkgs.length} Paket-Updates verfuegbar` : 'Alle Pakete aktuell'}
              </span>
            </div>

            {/* Package List */}
            {pendingPkgs.length > 0 && (
              <div className="bg-gray-900 rounded overflow-hidden">
                <table className="w-full text-xs">
                  <thead>
                    <tr className="text-gray-500 border-b border-gray-800">
                      <th className="text-left px-3 py-1.5">Paket</th>
                      <th className="text-left px-3 py-1.5">Aktuell</th>
                      <th className="text-left px-3 py-1.5">Neu</th>
                    </tr>
                  </thead>
                  <tbody>
                    {pendingPkgs.map((pkg, i) => (
                      <tr key={i} className="border-b border-gray-800/50">
                        <td className="px-3 py-1 text-gray-300 font-mono">{pkg.package}</td>
                        <td className="px-3 py-1 text-gray-500">{pkg.current_version}</td>
                        <td className="px-3 py-1 text-emerald-400">{pkg.new_version}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            )}
          </div>
        )}
      </div>

      {/* Normales Update */}
      <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-4">
        <h3 className="text-white font-semibold mb-1">Normales Update</h3>
        <p className="text-gray-500 text-xs mb-3">OPNsense Core + Paket-Updates installieren.</p>
        <div className="flex items-center gap-4">
          <button
            onClick={runUpdate}
            disabled={updating}
            className="flex items-center gap-2 bg-orange-600 hover:bg-orange-500 disabled:bg-gray-700 disabled:text-gray-500 text-white px-4 py-2 rounded text-sm transition-colors"
          >
            <Download className="w-4 h-4" />
            {updating ? 'Update laeuft...' : 'Update starten'}
          </button>
          <label className="flex items-center gap-2 text-sm text-gray-400 cursor-pointer">
            <input
              type="checkbox"
              checked={reboot}
              onChange={(e) => setReboot(e.target.checked)}
              className="rounded bg-gray-700 border-gray-600 text-orange-500 focus:ring-orange-500"
            />
            Nach Update neustarten
          </label>
        </div>
      </div>

      {/* Major Update */}
      <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-4">
        <h3 className="text-white font-semibold mb-1">Major-Update</h3>
        <p className="text-gray-500 text-xs mb-3">
          Upgrade auf neue OPNsense-Version (2 Phasen: Phase 1 = Base+Kernel + Reboot, Phase 2 = Packages).
        </p>
        <div className="flex items-center gap-3 mb-3">
          <input
            type="text"
            value={majorVer}
            onChange={(e) => setMajorVer(e.target.value)}
            placeholder="z.B. 26.1"
            className="bg-gray-900 border border-gray-700 text-white text-sm rounded px-3 py-1.5 w-28 focus:border-orange-500 focus:outline-none"
          />
          <select
            value={majorPhase}
            onChange={(e) => setMajorPhase(e.target.value)}
            className="bg-gray-900 border border-gray-700 text-white text-sm rounded px-3 py-1.5 focus:border-orange-500 focus:outline-none"
          >
            <option value="1">Phase 1 (Base+Kernel)</option>
            <option value="2">Phase 2 (Packages)</option>
          </select>
          {majorPhase === '1' && (
            <label className="flex items-center gap-2 text-sm text-gray-400 cursor-pointer">
              <input
                type="checkbox"
                checked={majorReboot}
                onChange={(e) => setMajorReboot(e.target.checked)}
                className="rounded bg-gray-700 border-gray-600 text-orange-500 focus:ring-orange-500"
              />
              Reboot
            </label>
          )}
        </div>
        <button
          onClick={runMajorUpdate}
          disabled={updating || !majorVer}
          className="flex items-center gap-2 bg-red-600 hover:bg-red-500 disabled:bg-gray-700 disabled:text-gray-500 text-white px-4 py-2 rounded text-sm transition-colors"
        >
          <Shield className="w-4 h-4" />
          {updating ? 'Update laeuft...' : `Major-Update Phase ${majorPhase} starten`}
        </button>
      </div>

      {/* Reboot */}
      <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-4">
        <h3 className="text-white font-semibold mb-1">Reboot</h3>
        <p className="text-gray-500 text-xs mb-3">Geraet manuell neu starten.</p>
        <button
          onClick={runReboot}
          className="flex items-center gap-2 bg-red-600/80 hover:bg-red-600 text-white px-4 py-2 rounded text-sm transition-colors"
        >
          Jetzt neustarten
        </button>
      </div>

      {/* Update-Ergebnis */}
      {updateResult && (
        <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-4">
          <h3 className="text-white font-semibold mb-2">Ergebnis</h3>
          {updateResult.error ? (
            <div className="text-red-400 text-sm">{updateResult.error}</div>
          ) : (
            <div className="space-y-2">
              {updateResult.message && (
                <div className="text-emerald-400 text-sm">{updateResult.message}</div>
              )}
              {updateResult.steps?.map((step, i) => (
                <div key={i} className="bg-gray-900 rounded p-2">
                  <div className="flex items-center gap-2 mb-1">
                    <div className={`w-2 h-2 rounded-full ${step.ok ? 'bg-emerald-400' : 'bg-red-400'}`} />
                    <span className="text-gray-300 text-xs font-mono">{step.step}</span>
                  </div>
                  {step.output && (
                    <pre className="text-gray-500 text-xs overflow-x-auto max-h-40 whitespace-pre-wrap">{step.output}</pre>
                  )}
                  {step.error && <div className="text-red-400 text-xs mt-1">{step.error}</div>}
                </div>
              ))}
              {updateResult.reboot_required && (
                <div className="flex items-center gap-2 text-red-400 text-sm">
                  <div className="w-2.5 h-2.5 rounded-full bg-red-400" />
                  Reboot erforderlich
                  {!updateResult.reboot_requested && (
                    <button onClick={runReboot} className="ml-2 text-xs bg-red-600 hover:bg-red-500 text-white px-2 py-1 rounded">
                      Jetzt neustarten
                    </button>
                  )}
                </div>
              )}
            </div>
          )}
        </div>
      )}
    </div>
  )
}

function AgentTab({ agent, status, platform }) {
  const [updating, setUpdating] = useState(false)
  const [msg, setMsg] = useState('')

  const requestUpdate = async () => {
    setUpdating(true)
    try {
      await api.requestAgentUpdate(agent.id)
      setMsg('Update angefordert — wird beim naechsten Updater-Zyklus ausgefuehrt')
    } catch (err) {
      setMsg(`Fehler: ${err.message}`)
    } finally {
      setUpdating(false)
    }
  }

  const lastHB = agent?.last_heartbeat ? new Date(agent.last_heartbeat) : null

  return (
    <div className="space-y-4">
      {/* Agent Update */}
      <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-4">
        <h3 className="text-white font-semibold mb-1">Agent Update</h3>
        <p className="text-gray-500 text-xs mb-3">Aktualisiert die Agent-Dateien remote ueber den bestehenden Agent-Kanal.</p>
        <button
          onClick={requestUpdate}
          disabled={updating || agent?.update_requested}
          className="flex items-center gap-2 bg-orange-600 hover:bg-orange-500 disabled:bg-gray-700 disabled:text-gray-500 text-white px-4 py-2 rounded text-sm transition-colors"
        >
          <Download className="w-4 h-4" />
          {agent?.update_requested ? 'Update ausstehend...' : updating ? 'Wird angefordert...' : 'Agent aktualisieren'}
        </button>
        {msg && <div className="text-xs text-emerald-400 mt-2">{msg}</div>}
      </div>

      {/* Nuetzliche Befehle */}
      <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-4">
        <h3 className="text-white font-semibold mb-3">Nuetzliche Befehle</h3>
        <div className="space-y-2">
          {(platform === 'linux' ? [
            { label: 'Service Status:', cmd: 'systemctl status rmm-agent' },
            { label: 'Logs anzeigen:', cmd: 'journalctl -u rmm-agent -f' },
            { label: 'Agent neustarten:', cmd: 'systemctl restart rmm-agent' },
          ] : [
            { label: 'Service Status:', cmd: 'service rmm_agent status' },
            { label: 'Logs anzeigen:', cmd: 'tail -f /var/log/rmm-agent.log' },
            { label: 'Agent neustarten:', cmd: 'service rmm_agent restart' },
            { label: 'Updater Status:', cmd: 'service rmm_updater status' },
            { label: 'Updater Logs:', cmd: 'tail -f /var/log/rmm-updater.log' },
          ]).map((item, i) => (
            <div key={i} className="flex items-center gap-3">
              <span className="text-gray-500 text-xs w-40 shrink-0">{item.label}</span>
              <code className="bg-gray-900 text-gray-300 text-xs px-2 py-1 rounded font-mono">{item.cmd}</code>
            </div>
          ))}
        </div>
      </div>

      {/* Agent Info */}
      <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-4">
        <h3 className="text-white font-semibold mb-3">Agent Info</h3>
        <div className="space-y-2">
          <div className="flex justify-between">
            <span className="text-gray-500 text-sm">Plattform:</span>
            <span className="text-white text-sm font-medium">{platform === 'linux' ? 'Linux' : platform === 'freebsd' ? 'FreeBSD / OPNsense' : platform}</span>
          </div>
          <div className="flex justify-between">
            <span className="text-gray-500 text-sm">Agent Version:</span>
            <span className="text-white text-sm font-medium">{agent?.agent_version || '--'}</span>
          </div>
          <div className="flex justify-between">
            <span className="text-gray-500 text-sm">Status:</span>
            <span className={`text-sm font-medium ${
              status === 'online' ? 'text-emerald-400' :
              status === 'stale' ? 'text-yellow-400' : 'text-gray-500'
            }`}>
              {status === 'online' ? 'Online' : status === 'stale' ? 'Verzoegert' : 'Offline'}
            </span>
          </div>
          <div className="flex justify-between">
            <span className="text-gray-500 text-sm">Letzter Heartbeat:</span>
            <span className="text-white text-sm">
              {lastHB ? lastHB.toLocaleString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit' }) : '--'}
            </span>
          </div>
          <div className="flex justify-between">
            <span className="text-gray-500 text-sm">Agent ID:</span>
            <span className="text-gray-400 text-xs font-mono">{agent?.id?.substring(0, 16) || '--'}...</span>
          </div>
          <div className="flex justify-between">
            <span className="text-gray-500 text-sm">Registriert:</span>
            <span className="text-gray-400 text-sm">
              {agent?.registered_at ? new Date(agent.registered_at).toLocaleString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' }) : '--'}
            </span>
          </div>
        </div>
      </div>
    </div>
  )
}

function HAProxyTab({ sys }) {
  const ha = sys?.haproxy
  if (!ha) return <div className="text-gray-500">Keine HAProxy-Daten</div>
  const info = ha.info || {}
  const entries = ha.entries || []

  return (
    <div className="space-y-4">
      <h3 className="text-sm font-medium text-gray-300">HAProxy Info</h3>
      <div className="grid grid-cols-4 gap-3">
        <StatusCard icon={Clock} value={info.uptime || '—'} label="Uptime" />
        <StatusCard icon={Network} value={info.current_conns} label="Aktive Verb." />
        <StatusCard icon={Shield} value={info.current_ssl} label="SSL Verb." />
        <StatusCard value={info.total_requests?.toLocaleString('de-DE') || '0'} label="Requests Total" />
      </div>

      <h3 className="text-sm font-medium text-gray-300">Proxies</h3>
      <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 overflow-hidden">
        <table className="w-full text-sm">
          <thead>
            <tr className="text-left text-gray-500 text-xs border-b border-gray-700">
              <th className="px-3 py-2">Proxy</th>
              <th className="px-3 py-2">Server</th>
              <th className="px-3 py-2">Typ</th>
              <th className="px-3 py-2">Status</th>
              <th className="px-3 py-2">Sessions</th>
              <th className="px-3 py-2">Requests</th>
              <th className="px-3 py-2">Traffic In</th>
              <th className="px-3 py-2">Traffic Out</th>
              <th className="px-3 py-2">Fehler</th>
            </tr>
          </thead>
          <tbody className="divide-y divide-gray-700/50">
            {entries.map((e, i) => (
              <tr key={i}>
                <td className="px-3 py-2 text-white">{e.proxy_name}</td>
                <td className="px-3 py-2 text-gray-400">{e.server_name}</td>
                <td className="px-3 py-2"><span className="text-xs px-1.5 py-0.5 rounded bg-gray-700 text-gray-300">{e.type}</span></td>
                <td className="px-3 py-2">
                  <span className={`text-xs px-1.5 py-0.5 rounded ${
                    ['OPEN', 'UP'].includes(e.status) ? 'bg-green-900/50 text-green-400' :
                    e.status === 'DOWN' ? 'bg-red-900/50 text-red-400' :
                    'bg-gray-700 text-gray-400'
                  }`}>{e.status}</span>
                </td>
                <td className="px-3 py-2 text-gray-400">{e.current_sessions} / {e.total_sessions?.toLocaleString('de-DE')}</td>
                <td className="px-3 py-2 text-gray-400">{e.requests_total?.toLocaleString('de-DE') || '—'}</td>
                <td className="px-3 py-2 text-gray-400">{formatBytes(e.bytes_in)}</td>
                <td className="px-3 py-2 text-gray-400">{formatBytes(e.bytes_out)}</td>
                <td className="px-3 py-2 text-gray-400">{(e.errors_req || 0) + (e.errors_conn || 0) + (e.errors_resp || 0)}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  )
}

function CaddyTab({ sys }) {
  const caddy = sys?.caddy
  if (!caddy) return <div className="text-gray-500">Keine Caddy-Daten</div>

  const upstreams = caddy.upstreams || []
  const healthyCount = upstreams.filter(u => u.healthy).length
  const activeRequests = upstreams.reduce((s, u) => s + (u.num_requests || 0), 0)
  const totalFails = upstreams.reduce((s, u) => s + (u.fails || 0), 0)

  return (
    <div className="space-y-4">
      <h3 className="text-sm font-medium text-gray-300">Caddy Reverse Proxy</h3>

      <div className="grid grid-cols-4 gap-3">
        <StatusCard icon={Server} value={caddy.version || '—'} label="Version" />
        <StatusCard icon={Network} value={`${healthyCount} / ${upstreams.length}`} label="Upstreams OK" />
        <StatusCard icon={Globe} value={activeRequests} label="Aktive Requests" />
        <StatusCard value={totalFails} label="Fehler gesamt" />
      </div>

      {upstreams.length > 0 && (
        <>
          <h3 className="text-sm font-medium text-gray-300">Upstreams</h3>
          <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 overflow-hidden">
            <table className="w-full text-sm">
              <thead>
                <tr className="text-left text-gray-500 text-xs border-b border-gray-700">
                  <th className="px-3 py-2">Adresse</th>
                  <th className="px-3 py-2">Status</th>
                  <th className="px-3 py-2">Aktive Req.</th>
                  <th className="px-3 py-2">Fehler</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-gray-700/50">
                {upstreams.map((u, i) => (
                  <tr key={i}>
                    <td className="px-3 py-2 text-white font-mono">{u.address}</td>
                    <td className="px-3 py-2">
                      <span className={`text-xs px-1.5 py-0.5 rounded ${
                        u.healthy ? 'bg-green-900/50 text-green-400' : 'bg-red-900/50 text-red-400'
                      }`}>{u.healthy ? 'Healthy' : 'Unhealthy'}</span>
                    </td>
                    <td className="px-3 py-2 text-gray-400">{u.num_requests}</td>
                    <td className="px-3 py-2 text-gray-400">{u.fails}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </>
      )}

      <h3 className="text-sm font-medium text-gray-300">Konfigurierte Sites</h3>
      <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 overflow-hidden">
        <table className="w-full text-sm">
          <thead>
            <tr className="text-left text-gray-500 text-xs border-b border-gray-700">
              <th className="px-3 py-2">Domain</th>
              <th className="px-3 py-2">Upstream</th>
              <th className="px-3 py-2">TLS</th>
            </tr>
          </thead>
          <tbody className="divide-y divide-gray-700/50">
            {(caddy.sites || []).map((s, i) => (
              <tr key={i}>
                <td className="px-3 py-2 text-white font-mono">{s.domain}</td>
                <td className="px-3 py-2 text-gray-400 font-mono">{s.upstream}</td>
                <td className="px-3 py-2">
                  <span className={`text-xs px-1.5 py-0.5 rounded ${
                    s.tls ? 'bg-green-900/50 text-green-400' : 'bg-red-900/50 text-red-400'
                  }`}>{s.tls ? 'Aktiv' : 'Aus'}</span>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  )
}

function gwColor(status) {
  const s = (status || '').toLowerCase()
  if (s === 'online' || s === 'none') return 'text-green-400'
  if (s === 'offline' || s === 'down') return 'text-red-400'
  return 'text-yellow-400'
}

function formatBytes(bytes) {
  if (!bytes || bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`
}

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