'use client'

import { useState, useEffect, useCallback } from 'react'
import { useTranslations } from 'next-intl'
import { Button } from '@/components/ui/button'
import { useMissionControl } from '@/store'
import { useWebSocket } from '@/lib/websocket'
import { buildGatewayWebSocketUrl } from '@/lib/gateway-url'

interface Gateway {
  id: number
  name: string
  host: string
  port: number
  token_set: boolean
  is_primary: number
  status: string
  last_seen: number | null
  latency: number | null
  sessions_count: number
  agents_count: number
  created_at: number
  updated_at: number
}

interface DirectConnection {
  id: number
  agent_id: number
  tool_name: string
  tool_version: string | null
  connection_id: string
  status: string
  last_heartbeat: number | null
  metadata: string | null
  created_at: number
  agent_name: string
  agent_status: string
  agent_role: string
}

interface GatewayHealthProbe {
  id: number
  name: string
  status: 'online' | 'offline' | 'error'
  latency: number | null
  gateway_version?: string | null
  compatibility_warning?: string
  error?: string
}

interface GatewayHealthLogEntry {
  status: string
  latency: number | null
  probed_at: number
  error: string | null
}

interface GatewayHistory {
  gatewayId: number
  name: string | null
  entries: GatewayHealthLogEntry[]
}

interface DiscoveredGateway {
  user: string
  port: number
  bind: string
  mode: string
  active: boolean
  tailscale?: { mode: string }
}

export function MultiGatewayPanel() {
  const t = useTranslations('multiGateway')
  const [gateways, setGateways] = useState<Gateway[]>([])
  const [directConnections, setDirectConnections] = useState<DirectConnection[]>([])
  const [discoveredGateways, setDiscoveredGateways] = useState<DiscoveredGateway[]>([])
  const [loading, setLoading] = useState(true)
  const [showAdd, setShowAdd] = useState(false)
  const [probing, setProbing] = useState<number | null>(null)
  const [healthByGatewayId, setHealthByGatewayId] = useState<Map<number, GatewayHealthProbe>>(new Map())
  const [historyByGatewayId, setHistoryByGatewayId] = useState<Record<number, GatewayHistory>>({})
  const { connection } = useMissionControl()
  const { connect } = useWebSocket()

  const fetchGateways = useCallback(async () => {
    try {
      const res = await fetch('/api/gateways')
      const data = await res.json()
      setGateways(data.gateways || [])
    } catch { /* ignore */ }
    setLoading(false)
  }, [])

  const fetchDirectConnections = useCallback(async () => {
    try {
      const res = await fetch('/api/connect')
      const data = await res.json()
      setDirectConnections(data.connections || [])
    } catch { /* ignore */ }
  }, [])

  const fetchDiscovered = useCallback(async () => {
    try {
      const res = await fetch('/api/gateways/discover')
      const data = await res.json()
      setDiscoveredGateways(data.gateways || [])
    } catch { /* ignore */ }
  }, [])

  const fetchHistory = useCallback(async () => {
    try {
      const res = await fetch('/api/gateways/health/history')
      const data = await res.json()
      const map: Record<number, GatewayHistory> = {}
      for (const entry of data.history || []) {
        map[entry.gatewayId] = entry
      }
      setHistoryByGatewayId(map)
    } catch {
      setHistoryByGatewayId({})
    }
  }, [])

  useEffect(() => { fetchGateways(); fetchDirectConnections(); fetchDiscovered(); fetchHistory() }, [fetchGateways, fetchDirectConnections, fetchDiscovered, fetchHistory])

  const gatewayMatchesConnection = useCallback((gw: Gateway): boolean => {
    const url = connection.url
    if (!url) return false
    const normalizedConn = url.toLowerCase()
    const normalizedHost = String(gw.host || '').toLowerCase()

    if (normalizedHost && normalizedConn.includes(normalizedHost)) return true
    if (normalizedConn.includes(`:${gw.port}`)) return true

    try {
      const derivedWs = buildGatewayWebSocketUrl({
        host: gw.host,
        port: gw.port,
        browserProtocol: window.location.protocol,
      }).toLowerCase()
      return normalizedConn.includes(derivedWs)
    } catch {
      return false
    }
  }, [connection.url])

  const shouldShowConnectionSummary =
    gateways.length === 0 ||
    !gateways.some(gatewayMatchesConnection)

  const setPrimary = async (gw: Gateway) => {
    await fetch('/api/gateways', {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ id: gw.id, is_primary: 1 }),
    })
    fetchGateways()
    fetchHistory()
  }

  const deleteGateway = async (id: number) => {
    await fetch('/api/gateways', {
      method: 'DELETE',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ id }),
    })
    fetchGateways()
    fetchHistory()
  }

  const connectTo = async (gw: Gateway) => {
    try {
      const res = await fetch('/api/gateways/connect', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ id: gw.id }),
      })
      if (!res.ok) return
      const payload = await res.json()

      const wsUrl = String(payload?.ws_url || buildGatewayWebSocketUrl({
        host: gw.host,
        port: gw.port,
        browserProtocol: window.location.protocol,
      }))
      const token = String(payload?.token || '')
      connect(wsUrl, token)
    } catch {
      // ignore: connection status will remain disconnected
    }
  }

  const probeAll = async () => {
    try {
      const res = await fetch("/api/gateways/health", { method: "POST" })
      const data = await res.json().catch(() => ({}))
      const rows = Array.isArray(data?.results) ? data.results as GatewayHealthProbe[] : []
      const mapped = new Map<number, GatewayHealthProbe>()
      for (const row of rows) {
        if (typeof row?.id === 'number') mapped.set(row.id, row)
      }
      setHealthByGatewayId(mapped)
    } catch { /* ignore */ }
    fetchGateways()
    fetchHistory()
  }

  const probeGateway = async (gw: Gateway) => {
    setProbing(gw.id)
    await probeAll()
    setProbing(null)
  }

  const disconnectCli = async (connectionId: string) => {
    try {
      await fetch('/api/connect', {
        method: 'DELETE',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ connection_id: connectionId }),
      })
      fetchDirectConnections()
    } catch { /* ignore */ }
  }

  return (
    <div className="p-4 md:p-6 max-w-5xl mx-auto space-y-6">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div>
          <h2 className="text-lg font-semibold text-foreground">{t('title')}</h2>
          <p className="text-xs text-muted-foreground mt-0.5">
            {t('description')}
          </p>
        </div>
        <div className="flex items-center gap-2">
          <Button
            onClick={probeAll}
            variant="secondary"
            size="sm"
          >
            {t('probeAll')}
          </Button>
          <Button
            onClick={() => setShowAdd(!showAdd)}
            size="sm"
          >
            {t('addGateway')}
          </Button>
        </div>
      </div>

      {/* Current connection info (shown only for unmanaged/unknown connections). */}
      {shouldShowConnectionSummary && (
        <div className="bg-card border border-border rounded-lg p-4">
          <div className="flex items-center gap-3">
            <span className={`w-2.5 h-2.5 rounded-full ${connection.isConnected ? 'bg-green-500' : 'bg-red-500 animate-pulse'}`} />
            <div>
              <div className="text-sm font-medium text-foreground">
                {connection.isConnected ? t('connected') : t('disconnected')}
              </div>
              <div className="text-xs text-muted-foreground">
                {connection.url || t('noActiveConnection')}
                {connection.latency != null && ` (${connection.latency}ms)`}
              </div>
            </div>
          </div>
        </div>
      )}

      {/* Add Form */}
      {showAdd && (
        <AddGatewayForm onAdded={() => { fetchGateways(); setShowAdd(false) }} onCancel={() => setShowAdd(false)} />
      )}

      {/* Gateway List */}
      {loading ? (
        <div className="text-center text-xs text-muted-foreground py-8">{t('loadingGateways')}</div>
      ) : gateways.length === 0 ? (
        <div className="text-center py-12 bg-card border border-border rounded-lg">
          <p className="text-sm text-muted-foreground">{t('noGateways')}</p>
          <p className="text-xs text-muted-foreground mt-1">{t('addGatewayHint')}</p>
        </div>
      ) : (
        <div className="space-y-2">
          {gateways.map(gw => (
            <GatewayCard
              key={gw.id}
              gateway={gw}
              health={healthByGatewayId.get(gw.id)}
              historyEntries={historyByGatewayId[gw.id]?.entries || []}
              isProbing={probing === gw.id}
              isCurrentlyConnected={gatewayMatchesConnection(gw)}
              onSetPrimary={() => setPrimary(gw)}
              onDelete={() => deleteGateway(gw.id)}
              onConnect={() => connectTo(gw)}
              onProbe={() => probeGateway(gw)}
            />
          ))}
        </div>
      )}

      {/* Discovered OS-Level Gateways (exclude already-registered ones) */}
      {discoveredGateways.filter(dg => !gateways.some(gw => gw.port === dg.port)).length > 0 && (
        <div>
          <div className="flex items-center justify-between mb-3">
            <div>
              <h3 className="text-sm font-semibold text-foreground">{t('discoveredGateways')}</h3>
              <p className="text-xs text-muted-foreground mt-0.5">
                {t('discoveredGatewaysDesc')}
              </p>
            </div>
            <Button
              onClick={fetchDiscovered}
              variant="secondary"
              size="xs"
              className="text-2xs"
            >
              {t('refresh')}
            </Button>
          </div>
          <div className="space-y-2">
            {discoveredGateways
              .filter(dg => !gateways.some(gw => gw.port === dg.port))
              .map(dg => (
                <div key={`${dg.user}-${dg.port}`} className="bg-card border border-border rounded-lg p-4">
                  <div className="flex items-start justify-between gap-3">
                    <div className="flex-1 min-w-0">
                      <div className="flex items-center gap-2">
                        <span className={`w-2 h-2 rounded-full ${dg.active ? 'bg-green-500' : 'bg-red-500'}`} />
                        <span className="text-sm font-semibold text-foreground">{dg.user}</span>
                        <span className={`text-2xs px-1.5 py-0.5 rounded font-medium ${
                          dg.active
                            ? 'bg-green-500/20 text-green-400 border border-green-500/30'
                            : 'bg-red-500/20 text-red-400 border border-red-500/30'
                        }`}>
                          {dg.active ? t('running') : t('stopped')}
                        </span>
                        {dg.tailscale?.mode && (
                          <span className="text-2xs px-1.5 py-0.5 rounded bg-violet-500/20 text-violet-400 border border-violet-500/30 font-medium">
                            TS:{dg.tailscale.mode}
                          </span>
                        )}
                      </div>
                      <div className="flex items-center gap-4 mt-1.5 text-xs text-muted-foreground">
                        <span className="font-mono">127.0.0.1:{dg.port}</span>
                        <span>{t('bind')}: {dg.bind}</span>
                        <span>{t('mode')}: {dg.mode}</span>
                      </div>
                    </div>
                    <Button
                      onClick={async () => {
                        await fetch('/api/gateways', {
                          method: 'POST',
                          headers: { 'Content-Type': 'application/json' },
                          body: JSON.stringify({
                            name: dg.user,
                            host: '127.0.0.1',
                            port: dg.port,
                            is_primary: false,
                          }),
                        })
                        fetchGateways()
                        fetchDiscovered()
                      }}
                      variant="secondary"
                      size="xs"
                      className="text-2xs"
                    >
                      {t('register')}
                    </Button>
                  </div>
                </div>
              ))}
          </div>
        </div>
      )}

      {/* Direct CLI Connections */}
      <div>
        <div className="flex items-center justify-between mb-3">
          <div>
            <h3 className="text-sm font-semibold text-foreground">{t('directCliConnections')}</h3>
            <p className="text-xs text-muted-foreground mt-0.5">
              {t('directCliDesc')}
            </p>
          </div>
          <Button
            onClick={fetchDirectConnections}
            variant="secondary"
            size="xs"
            className="text-2xs"
          >
            {t('refresh')}
          </Button>
        </div>
        {directConnections.length === 0 ? (
          <div className="text-center py-8 bg-card border border-border rounded-lg">
            <p className="text-xs text-muted-foreground">{t('noDirectConnections')}</p>
            <p className="text-2xs text-muted-foreground mt-1">
              {t('useApiConnect')} <code className="font-mono bg-secondary px-1 rounded">POST /api/connect</code> {t('toRegisterCli')}
            </p>
          </div>
        ) : (
          <div className="space-y-2">
            {directConnections.map(conn => (
              <div key={conn.id} className="bg-card border border-border rounded-lg p-4">
                <div className="flex items-start justify-between gap-3">
                  <div className="flex-1 min-w-0">
                    <div className="flex items-center gap-2">
                      <span className={`w-2 h-2 rounded-full ${conn.status === 'connected' ? 'bg-green-500' : 'bg-red-500'}`} />
                      <span className="text-sm font-semibold text-foreground">{conn.agent_name}</span>
                      <span className="text-2xs px-1.5 py-0.5 rounded bg-blue-500/20 text-blue-400 border border-blue-500/30 font-medium">
                        {conn.tool_name}{conn.tool_version ? ` v${conn.tool_version}` : ''}
                      </span>
                      <span className={`text-2xs px-1.5 py-0.5 rounded font-medium ${
                        conn.status === 'connected'
                          ? 'bg-green-500/20 text-green-400 border border-green-500/30'
                          : 'bg-red-500/20 text-red-400 border border-red-500/30'
                      }`}>
                        {conn.status.toUpperCase()}
                      </span>
                    </div>
                    <div className="flex items-center gap-4 mt-1.5 text-xs text-muted-foreground">
                      <span>{t('role')}: {conn.agent_role || 'cli'}</span>
                      <span>{t('heartbeat')}: {conn.last_heartbeat ? new Date(conn.last_heartbeat * 1000).toLocaleString() : t('never')}</span>
                      <span className="font-mono text-2xs">{conn.connection_id.slice(0, 8)}...</span>
                    </div>
                  </div>
                  {conn.status === 'connected' && (
                    <Button
                      onClick={() => disconnectCli(conn.connection_id)}
                      variant="ghost"
                      size="xs"
                      className="text-2xs text-red-400 hover:bg-red-500/10"
                    >
                      {t('disconnect')}
                    </Button>
                  )}
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  )
}

function GatewayCard({ gateway, health, historyEntries = [], isProbing, isCurrentlyConnected, onSetPrimary, onDelete, onConnect, onProbe }: {
  gateway: Gateway
  health?: GatewayHealthProbe
  historyEntries?: GatewayHealthLogEntry[]
  isProbing: boolean
  isCurrentlyConnected: boolean
  onSetPrimary: () => void
  onDelete: () => void
  onConnect: () => void
  onProbe: () => void
}) {
  const t = useTranslations('multiGateway')
  const statusColors: Record<string, string> = {
    online: 'bg-green-500',
    offline: 'bg-red-500',
    error: 'bg-amber-500',
    timeout: 'bg-amber-500',
    unknown: 'bg-muted-foreground/30',
  }

  const timelineEntries = historyEntries.length > 0 ? [...historyEntries].slice(0, 10).reverse() : []
  const latestEntry = historyEntries[0]

  const lastSeen = gateway.last_seen
    ? new Date(gateway.last_seen * 1000).toLocaleString()
    : t('neverProbed')
  const compatibilityWarning = health?.compatibility_warning

  return (
    <div className={`bg-card border rounded-lg p-4 transition-smooth ${
      isCurrentlyConnected ? 'border-green-500/30 bg-green-500/5' : 'border-border'
    }`}>
      <div className="flex items-start justify-between gap-3">
        <div className="flex-1 min-w-0">
          <div className="flex items-center gap-2">
            <span className={`w-2 h-2 rounded-full ${isCurrentlyConnected ? 'bg-green-500' : (statusColors[gateway.status] || statusColors.unknown)}`} />
            <h3 className="text-sm font-semibold text-foreground">{gateway.name}</h3>
            {gateway.is_primary ? (
              <span className="text-2xs px-1.5 py-0.5 rounded bg-primary/20 text-primary border border-primary/30 font-medium">
                {t('primary')}
              </span>
            ) : null}
            {isCurrentlyConnected && (
              <span className="text-2xs px-1.5 py-0.5 rounded bg-green-500/20 text-green-400 border border-green-500/30 font-medium">
                {t('connectedBadge')}
              </span>
            )}
          </div>
          <div className="flex items-center gap-4 mt-1.5 text-xs text-muted-foreground">
            <span className="font-mono">{gateway.host}:{gateway.port}</span>
            <span>{t('token')}: {gateway.token_set ? t('tokenSet') : t('tokenNone')}</span>
            {gateway.latency != null && <span>{t('latency')}: {gateway.latency}ms</span>}
            <span>{t('last')}: {lastSeen}</span>
          </div>
          {health?.gateway_version && (
            <div className="mt-1 text-2xs text-muted-foreground">
              {t('gatewayVersion')}: <span className="font-mono text-foreground/80">{health.gateway_version}</span>
            </div>
          )}
          {compatibilityWarning && (
            <div className="mt-1.5 text-2xs rounded border border-amber-500/30 bg-amber-500/10 text-amber-300 px-2 py-1">
              {compatibilityWarning}
            </div>
          )}
          <div className="flex flex-wrap items-center gap-2 mt-3 text-2xs text-muted-foreground">
            {timelineEntries.length > 0 ? (
              <div className="flex items-center gap-0.5">
                {timelineEntries.map((entry) => (
                  <span
                    key={`${entry.probed_at}-${entry.status}`}
                    className={`w-2.5 h-2.5 rounded-full ${statusColors[entry.status] || statusColors.unknown}`}
                    title={`${entry.status} ${entry.latency != null ? `(${entry.latency}ms)` : '(n/a)'} @ ${new Date(entry.probed_at * 1000).toLocaleTimeString()}${entry.error ? ` — ${entry.error}` : ''}`}
                  />
                ))}
              </div>
            ) : (
              <span className="text-2xs text-muted-foreground">{t('noHistory')}</span>
            )}
            <span title={t('colorKeyTitle')} className="text-2xs text-muted-foreground">
              {t('colorKey')}
            </span>
            {latestEntry?.latency != null && (
              <span className="text-2xs font-medium">{t('lastLatency', { ms: latestEntry.latency })}</span>
            )}
          </div>
        </div>
        <div className="flex items-center gap-1.5 shrink-0 flex-wrap justify-end">
          <Button
            onClick={onProbe}
            disabled={isProbing}
            variant="secondary"
            size="xs"
            className="text-2xs"
            title={t('probeGateway')}
          >
            {isProbing ? t('probing') : t('probe')}
          </Button>
          {!isCurrentlyConnected && (
            <Button
              onClick={onConnect}
              size="xs"
              className="text-2xs bg-blue-500/20 text-blue-400 hover:bg-blue-500/30"
              title={t('connectToGateway')}
            >
              {t('connect')}
            </Button>
          )}
          {!gateway.is_primary && (
            <>
              <Button
                onClick={onSetPrimary}
                variant="secondary"
                size="xs"
                className="text-2xs"
                title={t('setPrimaryTitle')}
              >
                {t('setPrimary')}
              </Button>
              <Button
                onClick={onDelete}
                variant="ghost"
                size="icon-xs"
                className="hover:text-red-400 hover:bg-red-500/10"
                title={t('removeGateway')}
              >
                <svg className="w-3.5 h-3.5" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round">
                  <path d="M3 4h10M6 4V3h4v1M5 4v8.5a.5.5 0 00.5.5h5a.5.5 0 00.5-.5V4" />
                </svg>
              </Button>
            </>
          )}
        </div>
      </div>
    </div>
  )
}

function AddGatewayForm({ onAdded, onCancel }: { onAdded: () => void; onCancel: () => void }) {
  const t = useTranslations('multiGateway')
  const [form, setForm] = useState({ name: '', host: '127.0.0.1', port: '18789', token: '' })
  const [saving, setSaving] = useState(false)
  const [error, setError] = useState('')

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault()
    setError('')
    setSaving(true)

    try {
      const res = await fetch('/api/gateways', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          name: form.name,
          host: form.host,
          port: parseInt(form.port),
          token: form.token,
          is_primary: false,
        }),
      })
      const data = await res.json()
      if (!res.ok) {
        setError(data.error || t('failedToAdd'))
        return
      }
      onAdded()
    } catch {
      setError(t('networkError'))
    } finally {
      setSaving(false)
    }
  }

  return (
    <form onSubmit={handleSubmit} className="bg-card border border-primary/20 rounded-lg p-4 space-y-3">
      <h3 className="text-sm font-semibold text-foreground">{t('addGatewayTitle')}</h3>

      <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-3">
        <div>
          <label className="block text-2xs text-muted-foreground mb-1">{t('name')}</label>
          <input
            type="text"
            value={form.name}
            onChange={e => setForm({ ...form, name: e.target.value })}
            placeholder={t('namePlaceholder')}
            className="w-full h-8 px-2.5 rounded-md bg-secondary border border-border text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-primary"
            required
          />
        </div>
        <div>
          <label className="block text-2xs text-muted-foreground mb-1">{t('host')}</label>
          <input
            type="text"
            value={form.host}
            onChange={e => setForm({ ...form, host: e.target.value })}
            className="w-full h-8 px-2.5 rounded-md bg-secondary border border-border text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-primary"
            required
          />
        </div>
        <div>
          <label className="block text-2xs text-muted-foreground mb-1">{t('port')}</label>
          <input
            type="number"
            value={form.port}
            onChange={e => setForm({ ...form, port: e.target.value })}
            className="w-full h-8 px-2.5 rounded-md bg-secondary border border-border text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-primary"
            required
          />
        </div>
        <div>
          <label className="block text-2xs text-muted-foreground mb-1">{t('token')}</label>
          <input
            type="password"
            value={form.token}
            onChange={e => setForm({ ...form, token: e.target.value })}
            placeholder={t('optional')}
            className="w-full h-8 px-2.5 rounded-md bg-secondary border border-border text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-primary"
          />
        </div>
      </div>

      {error && <p className="text-xs text-red-400">{error}</p>}

      <div className="flex gap-2 pt-1">
        <Button type="button" onClick={onCancel} variant="outline" size="sm">
          {t('cancel')}
        </Button>
        <Button type="submit" disabled={saving} size="sm">
          {saving ? t('adding') : t('addGatewaySubmit')}
        </Button>
      </div>
    </form>
  )
}
