import { useEffect, useState, useRef } from 'react'
import api from '../api/client'
import { Upload, RefreshCw, CheckCircle, AlertTriangle, ArrowUpCircle, X, Monitor, Server, Cpu, Package, Copy, Check } from 'lucide-react'
import { copyToClipboard } from '../utils/clipboard'

const PLATFORMS = [
  { id: 'freebsd', label: 'FreeBSD / OPNsense', icon: Server },
  { id: 'linux', label: 'Linux', icon: Monitor },
  { id: 'windows', label: 'Windows', icon: Cpu },
]

import { useSettingsStore } from '../stores/settings'

export default function Firmware() {
  const BACKEND_URL = useSettingsStore((s) => s.settings.backend_url_external || s.settings.backend_url_internal || '')
  const [firmwareData, setFirmwareData] = useState(null)
  const [installerData, setInstallerData] = useState(null)
  const [agents, setAgents] = useState([])
  const [customers, setCustomers] = useState([])
  const [loading, setLoading] = useState(true)
  const [uploading, setUploading] = useState(false)
  const [installerUploading, setInstallerUploading] = useState(false)
  const [version, setVersion] = useState('')
  const [platform, setPlatform] = useState('freebsd')
  const [installerPlatform, setInstallerPlatform] = useState('freebsd')
  const [msg, setMsg] = useState('')
  const [msgType, setMsgType] = useState('info')
  const fileRef = useRef(null)
  const installerFileRef = useRef(null)
  const [copied, setCopied] = useState(false)

  const load = async () => {
    try {
      const [fw, ag, inst, cu] = await Promise.all([
        api.getFirmwareInfo().catch(() => null),
        api.getAgents().catch(() => []),
        api.getInstallerInfo().catch(() => null),
        api.getCustomers().catch(() => []),
      ])
      setFirmwareData(fw)
      setAgents(Array.isArray(ag) ? ag : [])
      setInstallerData(inst)
      setCustomers(Array.isArray(cu) ? cu : [])
    } finally {
      setLoading(false)
    }
  }

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

  const showMsg = (text, type = 'info') => {
    setMsg(text)
    setMsgType(type)
    setTimeout(() => setMsg(''), 5000)
  }

  const getFwForPlatform = (p) => {
    if (!firmwareData?.platforms) return null
    return firmwareData.platforms.find(f => f.platform === p)
  }

  const handleUpload = async () => {
    const file = fileRef.current?.files?.[0]
    if (!file) return showMsg('Bitte Binary auswaehlen', 'error')
    if (!version.trim()) return showMsg('Bitte Version angeben', 'error')

    setUploading(true)
    try {
      const result = await api.uploadFirmware(version.trim(), platform, file)
      showMsg(`Firmware v${result.version} (${result.platform}) hochgeladen (${formatSize(result.size)})`, 'success')
      setVersion('')
      fileRef.current.value = ''
      load()
    } catch (err) {
      showMsg(`Upload fehlgeschlagen: ${err.message}`, 'error')
    } finally {
      setUploading(false)
    }
  }

  const requestUpdate = async (agentId, name) => {
    try {
      await api.requestAgentUpdate(agentId)
      showMsg(`Update fuer ${name} angefordert`, 'success')
      load()
    } catch (err) {
      showMsg(`Fehler: ${err.message}`, 'error')
    }
  }

  const cancelUpdate = async (agentId, name) => {
    try {
      await api.cancelAgentUpdate(agentId)
      showMsg(`Update-Anforderung fuer ${name} geloescht`, 'info')
      load()
    } catch (err) {
      showMsg(`Fehler: ${err.message}`, 'error')
    }
  }

  const requestAll = async () => {
    try {
      const result = await api.requestUpdateAll()
      showMsg(result.message || 'Update fuer alle angefordert', 'success')
      load()
    } catch (err) {
      showMsg(`Fehler: ${err.message}`, 'error')
    }
  }

  const formatSize = (bytes) => {
    if (!bytes) return '--'
    if (bytes > 1048576) return `${(bytes / 1048576).toFixed(1)} MB`
    return `${(bytes / 1024).toFixed(0)} KB`
  }

  if (loading) return <div className="text-gray-500">Laden...</div>

  const getFwForAgent = (agent) => {
    const p = agent.platform || 'freebsd'
    return getFwForPlatform(p)
  }

  const needsUpdate = (agent) => {
    const fw = getFwForAgent(agent)
    if (!fw) return false
    return agent.agent_version !== fw.version
  }

  const hasAnyFirmware = PLATFORMS.some(p => getFwForPlatform(p.id))

  return (
    <div className="max-w-4xl mx-auto space-y-6">
      <h1 className="text-2xl font-bold text-white">Agent-Firmware</h1>

      {/* Status Message */}
      {msg && (
        <div className={`rounded-lg px-4 py-3 text-sm flex items-center gap-2 ${
          msgType === 'error' ? 'bg-red-500/10 border border-red-500/30 text-red-400' :
          msgType === 'success' ? 'bg-emerald-500/10 border border-emerald-500/30 text-emerald-400' :
          'bg-blue-500/10 border border-blue-500/30 text-blue-400'
        }`}>
          {msgType === 'success' ? <CheckCircle className="w-4 h-4 shrink-0" /> :
           msgType === 'error' ? <AlertTriangle className="w-4 h-4 shrink-0" /> : null}
          {msg}
        </div>
      )}

      {/* Platform Firmware Overview */}
      <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-5">
        <h2 className="text-sm font-semibold text-gray-400 uppercase tracking-wider mb-4">Verfuegbare Firmware</h2>
        <div className="grid grid-cols-1 sm:grid-cols-3 gap-3">
          {PLATFORMS.map(p => {
            const fw = getFwForPlatform(p.id)
            const Icon = p.icon
            return (
              <div key={p.id} className={`rounded-lg border p-4 ${
                fw ? 'bg-gray-900/50 border-gray-700/50' : 'bg-gray-900/20 border-gray-800/50'
              }`}>
                <div className="flex items-center gap-2 mb-2">
                  <Icon className={`w-4 h-4 ${fw ? 'text-orange-400' : 'text-gray-600'}`} />
                  <span className={`text-sm font-medium ${fw ? 'text-white' : 'text-gray-600'}`}>{p.label}</span>
                </div>
                {fw ? (
                  <div className="space-y-1">
                    <div className="text-lg font-bold text-orange-400">v{fw.version}</div>
                    <div className="text-xs text-gray-500">{formatSize(fw.size)}</div>
                    <div className="text-[10px] text-gray-600 font-mono">{fw.hash?.substring(0, 16)}...</div>
                  </div>
                ) : (
                  <div className="text-xs text-gray-600 mt-1">Nicht hochgeladen</div>
                )}
              </div>
            )
          })}
        </div>
      </div>

      {/* Upload */}
      <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-5">
        <h2 className="text-sm font-semibold text-gray-400 uppercase tracking-wider mb-3">Neue Firmware hochladen</h2>
        <div className="flex flex-col gap-3">
          <div className="flex flex-wrap gap-3">
            <select
              value={platform}
              onChange={(e) => setPlatform(e.target.value)}
              className="bg-gray-900 border border-gray-700 rounded px-3 py-2 text-sm text-white focus:border-orange-500 focus:outline-none"
            >
              {PLATFORMS.map(p => (
                <option key={p.id} value={p.id}>{p.label}</option>
              ))}
            </select>
            <input
              type="text"
              placeholder="Version (z.B. 1.0.2)"
              value={version}
              onChange={(e) => setVersion(e.target.value)}
              className="bg-gray-900 border border-gray-700 rounded px-3 py-2 text-sm text-white placeholder-gray-500 focus:border-orange-500 focus:outline-none w-40"
            />
          </div>
          <div className="flex gap-3">
            <input
              type="file"
              ref={fileRef}
              className="bg-gray-900 border border-gray-700 rounded px-3 py-2 text-sm text-gray-400 file:mr-3 file:bg-gray-700 file:text-gray-300 file:border-0 file:rounded file:px-3 file:py-1 file:text-xs file:cursor-pointer flex-1"
            />
            <button
              onClick={handleUpload}
              disabled={uploading}
              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 shrink-0"
            >
              {uploading ? <RefreshCw className="w-4 h-4 animate-spin" /> : <Upload className="w-4 h-4" />}
              {uploading ? 'Hochladen...' : 'Hochladen'}
            </button>
          </div>
        </div>
      </div>

      {/* Installer Packages */}
      <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-5">
        <h2 className="text-sm font-semibold text-gray-400 uppercase tracking-wider mb-4">Installer-Pakete</h2>
        <p className="text-xs text-gray-500 mb-4">
          ZIP-Pakete mit install.sh und Plugin-Dateien. Werden auf neuen Geraeten per fetch heruntergeladen und ausgefuehrt.
        </p>

        {/* Existing installers */}
        {installerData?.installers?.length > 0 && (
          <div className="space-y-2 mb-4">
            {installerData.installers.map(inst => (
              <div key={inst.platform} className="flex items-center justify-between bg-gray-900/50 rounded-lg px-4 py-3 border border-gray-700/30">
                <div>
                  <div className="flex items-center gap-2">
                    <Package className="w-4 h-4 text-orange-400" />
                    <span className="text-white text-sm font-medium">
                      {inst.platform === 'linux' ? 'Linux' : inst.platform === 'windows' ? 'Windows' : 'OPNsense / FreeBSD'}
                    </span>
                  </div>
                  <div className="text-xs text-gray-500 mt-1">
                    {inst.filename} — {formatSize(inst.size)} — {new Date(inst.uploaded_at).toLocaleString('de-DE')}
                  </div>
                  <div className="text-[10px] text-gray-600 font-mono mt-0.5">{inst.sha256?.substring(0, 32)}...</div>
                </div>
              </div>
            ))}
          </div>
        )}

        {/* Install command */}
        {installerData?.installers?.some(i => i.platform === 'freebsd') && (
          <div className="mb-4 bg-gray-950 rounded p-3 relative">
            <div className="text-[10px] text-gray-500 mb-1">Installationsbefehl (OPNsense):</div>
            <pre className="text-xs font-mono text-orange-300 whitespace-pre-wrap">{`fetch --no-verify-peer --no-verify-hostname -o /tmp/installer.zip "${BACKEND_URL}/api/v1/installer/download?platform=freebsd&api_key=YOUR_API_KEY" && cd /tmp && unzip -o installer.zip && sh /tmp/install.sh`}</pre>
            <button
              onClick={() => {
                copyToClipboard(`fetch --no-verify-peer --no-verify-hostname -o /tmp/installer.zip "${BACKEND_URL}/api/v1/installer/download?platform=freebsd&api_key=YOUR_API_KEY" && cd /tmp && unzip -o installer.zip && sh /tmp/install.sh`)
                setCopied(true)
                setTimeout(() => setCopied(false), 2000)
              }}
              className="absolute top-2 right-2 text-gray-600 hover:text-orange-400 transition-colors"
            >
              {copied ? <Check className="w-4 h-4 text-green-400" /> : <Copy className="w-4 h-4" />}
            </button>
          </div>
        )}

        {installerData?.installers?.some(i => i.platform === 'windows') && (
          <div className="mb-4 bg-gray-950 rounded p-3 relative">
            <div className="text-[10px] text-gray-500 mb-1">Installationsbefehl (Windows, als Admin in PowerShell):</div>
            <pre className="text-xs font-mono text-sky-300 whitespace-pre-wrap">{`[Net.ServicePointManager]::ServerCertificateValidationCallback={$true}; $wc=New-Object Net.WebClient; $wc.Headers["X-API-Key"]="YOUR_AGENT_KEY"; $wc.DownloadFile("${BACKEND_URL}/api/v1/installer/download?platform=windows","C:\\rmm-install.zip"); Expand-Archive -Path C:\\rmm-install.zip -DestinationPath C:\\rmm-install -Force; Set-ExecutionPolicy Bypass -Scope Process -Force; C:\\rmm-install\\install.ps1 -BackendURL "${BACKEND_URL}" -APIKey "YOUR_AGENT_KEY" -AgentName "PC-NAME"`}</pre>
            <button
              onClick={() => {
                copyToClipboard(`[Net.ServicePointManager]::ServerCertificateValidationCallback={$true}; $wc=New-Object Net.WebClient; $wc.Headers["X-API-Key"]="YOUR_AGENT_KEY"; $wc.DownloadFile("${BACKEND_URL}/api/v1/installer/download?platform=windows","C:\\rmm-install.zip"); Expand-Archive -Path C:\\rmm-install.zip -DestinationPath C:\\rmm-install -Force; Set-ExecutionPolicy Bypass -Scope Process -Force; C:\\rmm-install\\install.ps1 -BackendURL "${BACKEND_URL}" -APIKey "YOUR_AGENT_KEY" -AgentName "PC-NAME"`)
                setCopied(true)
                setTimeout(() => setCopied(false), 2000)
              }}
              className="absolute top-2 right-2 text-gray-600 hover:text-sky-400 transition-colors"
            >
              {copied ? <Check className="w-4 h-4 text-green-400" /> : <Copy className="w-4 h-4" />}
            </button>
          </div>
        )}

        {/* Upload */}
        <div className="flex flex-wrap gap-3 items-end">
          <select
            value={installerPlatform}
            onChange={(e) => setInstallerPlatform(e.target.value)}
            className="bg-gray-900 border border-gray-700 rounded px-3 py-2 text-sm text-white focus:border-orange-500 focus:outline-none"
          >
            <option value="freebsd">OPNsense / FreeBSD</option>
            <option value="linux">Linux</option>
            <option value="windows">Windows</option>
          </select>
          <input
            type="file"
            ref={installerFileRef}
            accept=".zip,.sh"
            className="bg-gray-900 border border-gray-700 rounded px-3 py-2 text-sm text-gray-400 file:mr-3 file:bg-gray-700 file:text-gray-300 file:border-0 file:rounded file:px-3 file:py-1 file:text-xs file:cursor-pointer flex-1"
          />
          <button
            onClick={async () => {
              const file = installerFileRef.current?.files?.[0]
              if (!file) return showMsg('Bitte Datei auswaehlen', 'error')
              setInstallerUploading(true)
              try {
                const result = await api.uploadInstaller(installerPlatform, file)
                showMsg(`Installer fuer ${installerPlatform} hochgeladen (${formatSize(result.size)})`, 'success')
                installerFileRef.current.value = ''
                load()
              } catch (err) {
                showMsg(`Upload fehlgeschlagen: ${err.message}`, 'error')
              } finally {
                setInstallerUploading(false)
              }
            }}
            disabled={installerUploading}
            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 shrink-0"
          >
            {installerUploading ? <RefreshCw className="w-4 h-4 animate-spin" /> : <Upload className="w-4 h-4" />}
            {installerUploading ? 'Hochladen...' : 'Hochladen'}
          </button>
        </div>
      </div>

      {/* Agent List — nach Kunde gruppiert */}
      <div className="bg-gray-900 rounded-lg border border-gray-800 overflow-hidden">
        <div className="px-4 py-2.5 border-b border-gray-800 flex items-center justify-between">
          <span className="text-xs font-semibold text-gray-400 uppercase tracking-wider">
            Agents ({agents.length})
          </span>
          {hasAnyFirmware && (
            <button
              onClick={requestAll}
              className="flex items-center gap-1.5 text-orange-400 hover:text-orange-300 text-xs transition-colors"
            >
              <ArrowUpCircle className="w-3.5 h-3.5" />
              Alle updaten
            </button>
          )}
        </div>

        {(() => {
          // Gruppieren nach customer_id
          const groups = {}
          agents.forEach(a => {
            const gid = a.customer_id ?? '__none__'
            if (!groups[gid]) groups[gid] = []
            groups[gid].push(a)
          })
          const sorted = Object.entries(groups).sort(([a], [b]) => {
            if (a === '__none__') return 1
            if (b === '__none__') return -1
            const ca = customers.find(c => c.id === parseInt(a))
            const cb = customers.find(c => c.id === parseInt(b))
            return (ca?.number || '').localeCompare(cb?.number || '')
          })
          return sorted.map(([gid, gAgents]) => {
            const customer = gid !== '__none__' ? customers.find(c => c.id === parseInt(gid)) : null
            return (
              <div key={gid}>
                <div className="px-4 py-1 bg-gray-800/40 border-b border-gray-800/60">
                  <span className="text-[10px] font-semibold text-gray-500 uppercase tracking-wide">
                    {customer ? `${customer.number} — ${customer.name}` : 'Kein Kunde'}
                  </span>
                  <span className="text-[10px] text-gray-700 ml-1.5">({gAgents.length})</span>
                </div>
                {gAgents.map(agent => {
                  const outdated = needsUpdate(agent)
                  const pending = agent.update_requested
                  const agentPlatform = agent.platform || 'freebsd'
                  const fw = getFwForAgent(agent)
                  const isLinux   = agentPlatform === 'linux'
                  const isWindows = agentPlatform === 'windows'
                  const platformLabel = isWindows ? 'WIN' : isLinux ? 'LNX' : 'BSD'
                  const platformColor = isWindows
                    ? 'text-sky-400 bg-sky-900/30'
                    : isLinux
                      ? 'text-blue-400 bg-blue-900/30'
                      : 'text-orange-400 bg-orange-900/30'
                  return (
                    <div key={agent.id} className="px-4 py-1.5 flex items-center gap-2.5 hover:bg-gray-800/30 border-b border-gray-800/30 last:border-0">
                      <span className={`w-1.5 h-1.5 rounded-full flex-shrink-0 ${
                        agent.status === 'online' ? 'bg-green-400' :
                        agent.status === 'stale'  ? 'bg-yellow-400' : 'bg-gray-600'
                      }`} />
                      <span className="text-xs text-gray-300 flex-1 min-w-0 truncate">{agent.name}</span>
                      <span className={`text-[10px] px-1 py-0.5 rounded flex-shrink-0 ${platformColor}`}>
                        {platformLabel}
                      </span>
                      <span className={`text-[10px] font-mono flex-shrink-0 ${outdated ? 'text-yellow-400' : 'text-gray-600'}`}>
                        v{agent.agent_version || '—'}
                        {fw && outdated && <span className="text-gray-600"> → v{fw.version}</span>}
                      </span>
                      {pending && (
                        <span className="text-[10px] text-orange-400 flex-shrink-0">ausstehend</span>
                      )}
                      {pending ? (
                        <button onClick={() => cancelUpdate(agent.id, agent.name)}
                          className="text-gray-600 hover:text-red-400 transition-colors flex-shrink-0" title="Abbrechen">
                          <X className="w-3.5 h-3.5" />
                        </button>
                      ) : outdated ? (
                        <button onClick={() => requestUpdate(agent.id, agent.name)}
                          className="text-orange-400 hover:text-orange-300 transition-colors flex-shrink-0" title="Update anfordern">
                          <ArrowUpCircle className="w-3.5 h-3.5" />
                        </button>
                      ) : fw ? (
                        <CheckCircle className="w-3.5 h-3.5 text-green-700 flex-shrink-0" />
                      ) : null}
                    </div>
                  )
                })}
              </div>
            )
          })
        })()}
      </div>
    </div>
  )
}
