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 { BACKEND_URL } from '../config'

export default function Firmware() {
  const [firmwareData, setFirmwareData] = useState(null)
  const [installerData, setInstallerData] = useState(null)
  const [agents, setAgents] = 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] = await Promise.all([
        api.getFirmwareInfo().catch(() => null),
        api.getAgents().catch(() => []),
        api.getInstallerInfo().catch(() => null),
      ])
      setFirmwareData(fw)
      setAgents(Array.isArray(ag) ? ag : [])
      setInstallerData(inst)
    } 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' : '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>
        )}

        {/* 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>
          </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 */}
      <div className="bg-gray-800/50 rounded-lg border border-gray-700/50 p-5">
        <div className="flex items-center justify-between mb-4">
          <h2 className="text-sm font-semibold text-gray-400 uppercase tracking-wider">Agents</h2>
          {hasAnyFirmware && (
            <button
              onClick={requestAll}
              className="flex items-center gap-2 bg-orange-600/20 hover:bg-orange-600/30 text-orange-400 px-3 py-1.5 rounded text-xs transition-colors border border-orange-600/30"
            >
              <ArrowUpCircle className="w-3.5 h-3.5" />
              Alle updaten
            </button>
          )}
        </div>

        <div className="space-y-2">
          {agents.map((agent) => {
            const outdated = needsUpdate(agent)
            const pending = agent.update_requested
            const agentPlatform = agent.platform || 'freebsd'
            const fw = getFwForAgent(agent)
            const platformLabel = agentPlatform === 'linux' ? 'Linux' : 'FreeBSD'
            const platformColor = agentPlatform === 'linux' ? 'bg-blue-900/50 text-blue-400' : 'bg-orange-900/50 text-orange-400'
            return (
              <div key={agent.id} className="flex items-center justify-between bg-gray-900/50 rounded-lg px-4 py-3 border border-gray-700/30">
                <div className="min-w-0 flex-1">
                  <div className="flex items-center gap-2">
                    <span className={`w-2 h-2 rounded-full shrink-0 ${
                      agent.status === 'online' ? 'bg-emerald-500' :
                      agent.status === 'stale' ? 'bg-yellow-500' : 'bg-gray-600'
                    }`} />
                    <span className="text-white text-sm font-medium truncate">{agent.name}</span>
                    <span className={`text-[10px] px-1.5 py-0.5 rounded ${platformColor}`}>{platformLabel}</span>
                  </div>
                  <div className="flex items-center gap-3 mt-1">
                    <span className="text-xs text-gray-500">
                      Version: <span className={outdated ? 'text-yellow-400' : 'text-gray-400'}>{agent.agent_version || '--'}</span>
                      {fw && <span className="text-gray-600 ml-1">(aktuell: v{fw.version})</span>}
                      {!fw && <span className="text-gray-600 ml-1">(keine Firmware fuer {platformLabel})</span>}
                    </span>
                    {pending && (
                      <span className="text-[10px] px-1.5 py-0.5 rounded bg-orange-500/20 text-orange-400 border border-orange-500/30">
                        Update ausstehend
                      </span>
                    )}
                    {!outdated && fw && agent.agent_version && (
                      <span className="text-[10px] px-1.5 py-0.5 rounded bg-emerald-500/20 text-emerald-400 border border-emerald-500/30">
                        Aktuell
                      </span>
                    )}
                  </div>
                </div>
                <div className="flex items-center gap-2 shrink-0 ml-3">
                  {pending ? (
                    <button
                      onClick={() => cancelUpdate(agent.id, agent.name)}
                      className="flex items-center gap-1.5 bg-gray-700 hover:bg-gray-600 text-gray-300 px-3 py-1.5 rounded text-xs transition-colors"
                    >
                      <X className="w-3.5 h-3.5" />
                      Abbrechen
                    </button>
                  ) : outdated ? (
                    <button
                      onClick={() => requestUpdate(agent.id, agent.name)}
                      className="flex items-center gap-1.5 bg-orange-600 hover:bg-orange-500 text-white px-3 py-1.5 rounded text-xs transition-colors"
                    >
                      <ArrowUpCircle className="w-3.5 h-3.5" />
                      Update
                    </button>
                  ) : null}
                </div>
              </div>
            )
          })}
        </div>
      </div>
    </div>
  )
}
