import { useState, useEffect } from 'react'
import { Server, RefreshCw, Copy, CheckCircle, Trash2 } from 'lucide-react'
import { api } from '../lib/api'
import { useToast } from '../context/ToastContext'
import { Card, CardHeader, CardTitle, CardContent } from './ui/Card'
import { Button } from './ui/Button'
import { Input } from './ui/Input'

interface WorkerInfo {
  name: string
  encoders: string[]
  last_seen?: string
  online?: boolean
  info?: {
    hostname?: string
    ip?: string
    makemkv?: string
    handbrake?: string
  }
}

const ENCODER_LABELS: Record<string, string> = {
  'cpu-x264': 'CPU · H.264',
  'cpu-x265': 'CPU · H.265',
  'vaapi': 'GPU · VAAPI (AMD/Intel)',
  'nvenc': 'GPU · NVENC (NVIDIA)',
}

function relativeZeit(iso?: string): string {
  if (!iso) return 'nie'
  const sekunden = Math.floor((Date.now() - new Date(iso).getTime()) / 1000)
  if (sekunden < 90) return 'gerade eben'
  if (sekunden < 3600) return `vor ${Math.floor(sekunden / 60)} min`
  return `vor ${Math.floor(sekunden / 3600)} h`
}

export default function WorkerVerwaltung() {
  const [workers, setWorkers] = useState<WorkerInfo[]>([])
  const [kopiert, setKopiert] = useState(false)
  const [variante, setVariante] = useState<'linux' | 'windows'>('linux')
  // BEWUSST leer: kein window.location.hostname-Default. Der füllte früher
  // die Adresse, über die man das UI geöffnet hat (z. B. den eigenen PC hinter
  // einem Proxy/Forward) — und die ist NICHT zwingend die direkte LAN-IP der
  // Rippy-Maschine, die der Worker für Redis/Postgres braucht. Lieber bewusst
  // eintragen lassen als eine falsche Adresse vorgaukeln.
  const [rippyHost, setRippyHost] = useState('')
  const { toast } = useToast()

  // Für die Befehle: leeres Feld → sichtbarer Platzhalter (Befehl ist dann
  // erkennbar unvollständig, statt still auf die falsche Adresse zu zeigen).
  const hostFuerBefehl = rippyHost || '<RIPPY-IP>'

  const siehtOeffentlichAus =
    rippyHost !== '' &&
    !/^(\d{1,3}\.){3}\d{1,3}$/.test(rippyHost) &&
    !rippyHost.endsWith('.local') &&
    rippyHost !== 'localhost' &&
    rippyHost.includes('.')

  const laden = (manuell = false) => {
    api.get('/capabilities')
      .then(r => {
        setWorkers(r.data.workers || [])
        if (manuell) toast('success', 'Worker-Liste aktualisiert')
      })
      .catch(() => { if (manuell) toast('error', 'Worker-Liste konnte nicht geladen werden') })
  }

  useEffect(() => {
    laden()
    const interval = setInterval(laden, 15000)
    return () => clearInterval(interval)
  }, [])

  const installBefehl = variante === 'linux'
    ? [
        `git clone <rippy-repo-url> rippy && cd rippy`,
        `RIPPY_HOST=${hostFuerBefehl} WORKER_NAME=mein-pc \\`,
        `  docker compose -f deploy/remote-transcode-worker.yml up -d --build`,
      ].join('\n')
    : [
        `iwr http://${hostFuerBefehl}/api/worker-setup/windows -OutFile install-rippy-worker.ps1`,
        `powershell -ExecutionPolicy Bypass -File .\\install-rippy-worker.ps1 \``,
        `  -RippyHost ${hostFuerBefehl} -WorkerName mein-pc`,
      ].join('\n')

  const kopieren = () => {
    navigator.clipboard.writeText(installBefehl).then(() => {
      setKopiert(true)
      setTimeout(() => setKopiert(false), 2000)
    })
  }

  return (
    <div className="space-y-6">
      {/* Verbundene Worker */}
      <Card>
        <CardHeader>
          <CardTitle className="flex items-center gap-2">
            <Server size={20} className="text-amber-500" />
            <span>Verbundene Worker</span>
          </CardTitle>
          <Button variant="ghost" size="sm" onClick={() => laden(true)} title="Worker neu laden">
            <RefreshCw size={16} />
          </Button>
        </CardHeader>
        <CardContent>
          {workers.length === 0 ? (
            <p className="text-sm text-slate-500 dark:text-slate-400">Noch kein Worker gemeldet.</p>
          ) : (
            <div className="space-y-2.5">
              {workers.map(w => (
                <div key={w.name} className="flex items-center justify-between p-3.5 rounded-xl border border-slate-200/80 dark:border-slate-800 bg-slate-50 dark:bg-slate-950/80">
                  <div className="flex items-center gap-3 min-w-0">
                    <span
                      className={`w-2.5 h-2.5 rounded-full flex-shrink-0 ${w.online ? 'bg-emerald-500 shadow-sm shadow-emerald-500/50' : 'bg-rose-500'}`}
                      title={w.online ? 'erreichbar (Ping OK)' : 'nicht erreichbar'}
                    />
                    <Server size={18} className="text-slate-400 dark:text-slate-500" />
                    <div className="min-w-0">
                      <p className="text-sm font-medium truncate text-slate-900 dark:text-slate-200">{w.name}</p>
                      <p className="text-xs text-slate-500 dark:text-slate-400">
                        {w.online ? 'online' : 'offline'} · Lebenszeichen {relativeZeit(w.last_seen)}
                        {w.info?.ip ? ` · IP ${w.info.ip}` : ''}
                        {w.info?.hostname && w.info.hostname !== w.name ? ` · ID ${w.info.hostname}` : ''}
                      </p>
                    </div>
                  </div>
                  <div className="flex items-center gap-2">
                    <div className="flex flex-wrap gap-1 justify-end">
                      {w.encoders.map(e => (
                        <span key={e} className={`text-xs px-2.5 py-0.5 rounded-md font-medium border ${
                          e.startsWith('cpu')
                            ? 'bg-slate-200/80 dark:bg-slate-800 text-slate-700 dark:text-slate-300 border-slate-300 dark:border-slate-700'
                            : 'bg-emerald-500/15 text-emerald-600 dark:text-emerald-400 border-emerald-500/30'
                        }`}>
                          {ENCODER_LABELS[e] || e}
                        </span>
                      ))}
                    </div>
                    {!w.online && (
                      <button
                        onClick={() => {
                          api.delete(`/workers/${encodeURIComponent(w.name)}`)
                            .then(() => { toast('success', `„${w.name}" entfernt — ein aktiver Worker meldet sich binnen 1 min zurück`); laden() })
                            .catch(() => toast('error', 'Entfernen fehlgeschlagen'))
                        }}
                        title="Verwaisten Eintrag entfernen"
                        className="p-1.5 rounded-lg text-rose-500 hover:bg-rose-500/10 transition-colors"
                      >
                        <Trash2 size={14} />
                      </button>
                    )}
                  </div>
                </div>
              ))}
            </div>
          )}
        </CardContent>
      </Card>

      {/* Neue Maschine anbinden */}
      <Card>
        <CardHeader>
          <CardTitle>Maschine als Encoding-Worker anbinden</CardTitle>
        </CardHeader>
        <CardContent className="space-y-4">
          <div className="max-w-md">
            <Input
              label="LAN-IP der Rippy-Maschine (Docker-Host)"
              value={rippyHost}
              onChange={e => setRippyHost(e.target.value.trim())}
              placeholder="z. B. 192.168.178.162"
            />
            <p className="text-xs mt-2 text-slate-500 dark:text-slate-400">
              Die IP der Maschine, auf der <strong>Rippy selbst</strong> (Docker) läuft — meist deine
              Server-/NAS-VM. <strong>Nicht</strong> die IP des PCs, auf dem der Worker läuft, und auch
              dann diese direkte LAN-IP eintragen, wenn du dieses UI über eine andere Adresse
              (Domain/Proxy/Portweiterleitung) geöffnet hast. Der Worker spricht Redis/Postgres direkt
              an (Ports 6379/5432) — das klappt nur mit der echten LAN-IP im Heimnetz.
            </p>
            {siehtOeffentlichAus && (
              <p className="text-xs mt-2 p-3 rounded-xl bg-amber-500/10 border border-amber-500/20 text-amber-700 dark:text-amber-300">
                ⚠️ Das sieht nach einer externen Domain aus (Reverse-Proxy) — die geht nicht. Bitte die
                <strong> LAN-IP</strong> der Rippy-Maschine eintragen, z. B. 192.168.178.162.
              </p>
            )}
          </div>

          <div className="flex gap-2">
            {([['linux', '🐧 Linux (Docker)'], ['windows', '🪟 Windows (nativ, ohne Docker)']] as const).map(([wert, label]) => (
              <Button
                key={wert}
                variant={variante === wert ? 'amber' : 'secondary'}
                size="sm"
                onClick={() => setVariante(wert)}
              >
                {label}
              </Button>
            ))}
          </div>

          <p className="text-xs text-slate-500 dark:text-slate-400">
            {variante === 'linux'
              ? 'Auf der Linux-Maschine (mit Docker) ausführen — WORKER_NAME frei wählen, unter dem Namen taucht sie oben auf und übernimmt Kompressions-Jobs. GPU wird erkannt und angezeigt.'
              : 'In einer PowerShell auf dem Windows-PC ausführen (braucht nur Python 3.10+ — kein Docker, kein git). Der Installer holt Worker-Code und HandBrake automatisch.'}
          </p>

          <div className="relative rounded-xl p-4 font-mono text-xs whitespace-pre overflow-x-auto bg-slate-900 text-slate-200 border border-slate-800">
            {installBefehl}
            <button
              onClick={kopieren}
              className="absolute top-3 right-3 p-1.5 rounded-lg bg-slate-800 text-slate-300 hover:bg-slate-700 hover:text-white transition-colors"
              title="Kopieren"
            >
              {kopiert ? <CheckCircle size={15} className="text-emerald-400" /> : <Copy size={15} />}
            </button>
          </div>

          <p className="text-xs text-slate-500 dark:text-slate-400">
            Beide Varianten bedienen nur die Kompressions-Queue — gerippt wird immer hier, wo das Laufwerk hängt.
          </p>
        </CardContent>
      </Card>
    </div>
  )
}
