"use client"

import { Fragment, useEffect, useMemo, useState } from "react"
import { PageHeader } from "@/components/page-header"
import { StatusBadge } from "@/components/status-badge"
import { servers as initialServers } from "@/lib/data"
import type { ServerType, Server, WanUplink } from "@/lib/data"

// ─── Backend integration ──────────────────────────────────────────────────────

import { useDataSource } from "@/lib/data-source"

interface BackendServer {
  id: number; name: string; host: string; port: number
  useSsl: boolean; verifySsl: boolean; username: string; password: string
  type: ServerType; site: string; country: string; asn: string
  comment: string; enabled: boolean
  lanSubnet: string
  wanUplinks: WanUplink[]
  status: "online" | "offline" | null; latency: number | null
  os: string | null; model: string | null; uptime: string | null
  cpuLoad: number | null; freeMemory: number | null; totalMemory: number | null
  identityName: string | null
  sessions: number; polledAt: string | null
  createdAt: string; updatedAt: string
}

function toFrontend(s: BackendServer): Server {
  return {
    id:       String(s.id),
    name:     s.name || s.host,
    host:     s.host,
    type:     s.type,
    site:     s.site,
    country:  s.country,
    asn:      s.asn,
    model:    s.model ?? "—",
    os:       s.os ?? "—",
    enabled:  s.enabled,
    status:   s.status ?? "offline",
    latency:  s.latency != null ? Math.round(s.latency) : null,
    sessions: s.sessions ?? 0,
    comment:  s.comment || undefined,
    lanSubnet: s.lanSubnet || undefined,
    wanUplinks: Array.isArray(s.wanUplinks) && s.wanUplinks.length ? s.wanUplinks : undefined,
    // carry extra fields needed for expanded view
    uptime:       s.uptime ?? undefined,
    cpuLoad:      s.cpuLoad ?? undefined,
    freeMemory:   s.freeMemory ?? undefined,
    totalMemory:  s.totalMemory ?? undefined,
    polledAt:     s.polledAt ?? undefined,
  }
}

function makeApiFetch(backendUrl: string) {
  return async function apiFetch<T>(path: string, init?: RequestInit): Promise<T> {
    const headers: HeadersInit = init?.body
      ? { "Content-Type": "application/json" }
      : {}
    const res = await fetch(backendUrl.replace(/\/$/, "") + path, {
      ...init,
      headers: { ...headers, ...(init?.headers ?? {}) },
    })
    if (!res.ok) {
      const err = await res.json().catch(() => ({ error: res.statusText })) as { error?: string }
      throw new Error(err.error ?? res.statusText)
    }
    // 204 No Content
    if (res.status === 204) return undefined as T
    return res.json() as Promise<T>
  }
}
import { Flag } from "@/components/flag"
import { cn } from "@/lib/utils"
import { Card, CardContent } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import {
  Sheet, SheetContent, SheetHeader, SheetTitle,
  SheetDescription, SheetFooter, SheetClose,
} from "@/components/ui/sheet"
import {
  DropdownMenu, DropdownMenuTrigger, DropdownMenuContent,
  DropdownMenuItem, DropdownMenuSeparator, DropdownMenuLabel, DropdownMenuGroup,
} from "@/components/ui/dropdown-menu"
import {
  SearchIcon, RefreshCwIcon, DownloadIcon, PlusIcon, TrashIcon,
  MoreHorizontalIcon, EyeIcon, EyeOffIcon,
  ChevronRightIcon, ChevronDownIcon,
  CheckCircleIcon, XCircleIcon, LoaderCircleIcon,
  ShieldIcon, WifiIcon, PencilIcon, PowerIcon, Trash2Icon, ExternalLinkIcon,
  HomeIcon, ServerIcon, NetworkIcon,
} from "lucide-react"

// ─── RouterOS version utilities ───────────────────────────────────────────────

/** Numeric version score: "7.20.1 (stable)" → 720, "7.14.2" → 714, "7.9" → 709 */
function rosVer(os: string): number {
  const m = os.match(/(\d+)\.(\d+)/)
  if (!m) return 0
  return parseInt(m[1], 10) * 100 + parseInt(m[2], 10)
}

interface RosFeature { name: string; minVer: number; label: string; desc: string }

const ROS_FEATURES: RosFeature[] = [
  { name: "WireGuard",             minVer: 701, label: "7.1+",  desc: "WireGuard VPN туннели" },
  { name: "Container",             minVer: 704, label: "7.4+",  desc: "Docker-совместимые контейнеры" },
  { name: "BFD",                   minVer: 705, label: "7.5+",  desc: "Bidirectional Forwarding Detection" },
  { name: "Large Communities",     minVer: 707, label: "7.7+",  desc: "BGP Large Communities (RFC 8092)" },
  { name: "VXLAN",                 minVer: 710, label: "7.10+", desc: "VXLAN overlay туннели" },
  { name: "RPKI",                  minVer: 713, label: "7.13+", desc: "Route Origin Validation" },
  { name: "BGP Flowspec",          minVer: 714, label: "7.14+", desc: "BGP Flow Spec (RFC 8955)" },
  { name: "IPv6 Firewall",         minVer: 715, label: "7.15+", desc: "Расширенный IPv6 Firewall" },
  { name: "REST API v2",           minVer: 716, label: "7.16+", desc: "Обновлённый REST API" },
  { name: "VRF Enhanced",          minVer: 717, label: "7.17+", desc: "Расширенная поддержка VRF" },
]

function RosBadge({ os }: { os: string }) {
  const v = rosVer(os)
  const cls = v >= 715
    ? "bg-[var(--status-online-bg)] text-[var(--status-online-fg)] border-current/20"
    : v >= 710
      ? "bg-[var(--status-degraded-bg)] text-[var(--status-degraded-fg)] border-current/20"
      : "bg-[var(--status-offline-bg)] text-[var(--status-offline-fg)] border-current/20"
  return (
    <span className={cn("text-xs font-mono border rounded px-2 py-0.5", cls)}>
      {os}
    </span>
  )
}

// ─── Countries ───────────────────────────────────────────────────────────────

const COUNTRIES = [
  { code: "RU", label: "Россия" }, { code: "DE", label: "Германия" },
  { code: "NL", label: "Нидерланды" }, { code: "SG", label: "Сингапур" },
  { code: "FI", label: "Финляндия" }, { code: "SE", label: "Швеция" },
  { code: "FR", label: "Франция" }, { code: "GB", label: "Великобритания" },
  { code: "PL", label: "Польша" }, { code: "US", label: "США" },
  { code: "UA", label: "Украина" }, { code: "TR", label: "Турция" },
  { code: "JP", label: "Япония" }, { code: "HK", label: "Гонконг" },
  { code: "KZ", label: "Казахстан" }, { code: "BY", label: "Беларусь" },
  { code: "LT", label: "Литва" }, { code: "LV", label: "Латвия" },
  { code: "EE", label: "Эстония" }, { code: "CZ", label: "Чехия" },
  { code: "AT", label: "Австрия" }, { code: "CH", label: "Швейцария" },
  { code: "NO", label: "Норвегия" },
]

// ─── Type config ─────────────────────────────────────────────────────────────

const TYPE_LABELS: Record<ServerType, string> = {
  "jump-host":   "JumpHost",
  "exit-node":   "Exit Node",
  "home-router": "Home Router",
}

const TYPE_STYLES: Record<ServerType, string> = {
  "jump-host":   "bg-violet-500/10 text-violet-400 border-violet-500/20",
  "exit-node":   "bg-sky-500/10 text-sky-400 border-sky-500/20",
  "home-router": "bg-emerald-500/10 text-emerald-400 border-emerald-500/20",
}

const TYPE_ICONS: Record<ServerType, React.ReactNode> = {
  "jump-host":   <ServerIcon className="size-3 mr-1" />,
  "exit-node":   <NetworkIcon className="size-3 mr-1" />,
  "home-router": <HomeIcon className="size-3 mr-1" />,
}

function TypeBadge({ type }: { type: ServerType }) {
  return (
    <span className={cn(
      "inline-flex items-center text-xs font-medium border rounded px-2 py-0.5",
      TYPE_STYLES[type],
    )}>
      {TYPE_ICONS[type]}{TYPE_LABELS[type]}
    </span>
  )
}

// ─── Shared small components ──────────────────────────────────────────────────

function Field({ label, hint, required, children }: {
  label: string; hint?: string; required?: boolean; children: React.ReactNode
}) {
  return (
    <div className="flex flex-col gap-1.5">
      <label className="text-sm font-medium">
        {label}{required && <span className="text-destructive ml-0.5">*</span>}
      </label>
      {children}
      {hint && <p className="text-xs text-muted-foreground">{hint}</p>}
    </div>
  )
}

function Toggle({ checked, onChange }: { checked: boolean; onChange: (v: boolean) => void }) {
  return (
    <button type="button" role="switch" aria-checked={checked}
      onClick={() => onChange(!checked)}
      className={cn("relative inline-flex h-5 w-9 shrink-0 rounded-full border-2 border-transparent transition-colors",
        checked ? "bg-primary" : "bg-input")}>
      <span className={cn("pointer-events-none block h-4 w-4 rounded-full bg-white shadow-sm transition-transform",
        checked ? "translate-x-4" : "translate-x-0")} />
    </button>
  )
}

function SectionTitle({ children }: { children: React.ReactNode }) {
  return (
    <div className="flex items-center gap-2 py-0.5">
      <span className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">{children}</span>
      <div className="flex-1 h-px bg-border" />
    </div>
  )
}

function SegmentedControl<T extends string>({ value, onChange, options }: {
  value: T; onChange: (v: T) => void; options: { value: T; label: string }[]
}) {
  return (
    <div className="flex items-center gap-1 rounded-md border border-border bg-muted/40 p-0.5 w-fit">
      {options.map((o) => (
        <button key={o.value} type="button" onClick={() => onChange(o.value)}
          className={cn("px-3 py-1 text-sm rounded transition-colors",
            value === o.value ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground")}>
          {o.label}
        </button>
      ))}
    </div>
  )
}

// ─── Country field ────────────────────────────────────────────────────────────

function CountryField({ value, onChange }: { value: string; onChange: (v: string) => void }) {
  const [query, setQuery] = useState("")
  const q = query.trim().toUpperCase()
  const visible = q.length === 0
    ? COUNTRIES
    : COUNTRIES.filter(c => c.code.startsWith(q) || c.label.toLowerCase().includes(query.trim().toLowerCase()))

  return (
    <div className="flex flex-col gap-2">
      <label className="text-sm font-medium">Страна <span className="text-destructive">*</span></label>
      <div className="flex items-center gap-2">
        <div className="relative flex-1">
          <Input placeholder="Поиск или код (RU, DE…)" value={query}
            onChange={e => {
              const v = e.target.value.toUpperCase().slice(0, 3)
              setQuery(v)
              if (v.length === 2) {
                const match = COUNTRIES.find(c => c.code === v)
                if (match) onChange(match.code)
              }
            }}
            className="font-mono pr-10 h-8 text-sm" />
          {value && (
            <span className="absolute right-2.5 top-1/2 -translate-y-1/2">
              <Flag code={value} size={20} />
            </span>
          )}
        </div>
        {value && (
          <span className="text-sm font-mono text-muted-foreground shrink-0">
            {COUNTRIES.find(c => c.code === value)?.label ?? value}
          </span>
        )}
      </div>
      <div className="grid grid-cols-5 gap-1.5 max-h-52 overflow-y-auto pr-0.5">
        {visible.map(c => (
          <button key={c.code} type="button"
            onClick={() => { onChange(c.code); setQuery("") }}
            title={`${c.code} · ${c.label}`}
            className={cn(
              "flex flex-col items-center gap-1 px-1 py-2 rounded-lg border text-[10px] transition-all",
              value === c.code
                ? "border-primary bg-primary/5 ring-1 ring-primary/30 font-semibold text-primary"
                : "border-border hover:border-muted-foreground/40 hover:bg-muted/40 text-muted-foreground",
            )}>
            <Flag code={c.code} size={24} />
            <span className="font-mono leading-none">{c.code}</span>
          </button>
        ))}
      </div>
    </div>
  )
}

// ─── WAN uplinks editor ───────────────────────────────────────────────────────

function newWan(): WanUplink {
  return { id: `w${Date.now()}`, name: "", isp: "", iface: "ether1", ip: "", maxDl: 100, maxUl: 100 }
}

function WanUplinkEditor({ wans, onChange }: {
  wans: WanUplink[]
  onChange: (wans: WanUplink[]) => void
}) {
  function updateWan(id: string, patch: Partial<WanUplink>) {
    onChange(wans.map(w => w.id === id ? { ...w, ...patch } : w))
  }
  function removeWan(id: string) { onChange(wans.filter(w => w.id !== id)) }
  function addWan() { onChange([...wans, newWan()]) }

  return (
    <div className="flex flex-col gap-3">
      {wans.map((wan, idx) => (
        <div key={wan.id} className="rounded-lg border border-border bg-muted/20 p-3 flex flex-col gap-3">
          <div className="flex items-center justify-between">
            <span className="text-xs font-semibold text-muted-foreground uppercase tracking-wide">
              WAN {idx + 1}
            </span>
            <button type="button" onClick={() => removeWan(wan.id)}
              className="text-muted-foreground hover:text-destructive transition-colors">
              <TrashIcon className="size-3.5" />
            </button>
          </div>
          <div className="grid grid-cols-2 gap-2">
            <Field label="Имя" required>
              <Input className="h-8 font-mono text-xs" placeholder="WAN1-RT"
                value={wan.name} onChange={e => updateWan(wan.id, { name: e.target.value })} />
            </Field>
            <Field label="Интерфейс">
              <Input className="h-8 font-mono text-xs" placeholder="ether1"
                value={wan.iface} onChange={e => updateWan(wan.id, { iface: e.target.value })} />
            </Field>
            <Field label="Провайдер (ISP)">
              <Input className="h-8 text-xs" placeholder="Rostelecom"
                value={wan.isp} onChange={e => updateWan(wan.id, { isp: e.target.value })} />
            </Field>
            <Field label="Внешний IP">
              <Input className="h-8 font-mono text-xs" placeholder="94.25.168.1"
                value={wan.ip} onChange={e => updateWan(wan.id, { ip: e.target.value })} />
            </Field>
            <Field label="↓ Макс. Мбит">
              <Input className="h-8 font-mono text-xs" type="number" min={1}
                value={wan.maxDl} onChange={e => updateWan(wan.id, { maxDl: Number(e.target.value) })} />
            </Field>
            <Field label="↑ Макс. Мбит">
              <Input className="h-8 font-mono text-xs" type="number" min={1}
                value={wan.maxUl} onChange={e => updateWan(wan.id, { maxUl: Number(e.target.value) })} />
            </Field>
          </div>
        </div>
      ))}
      <Button type="button" variant="outline" size="sm" className="w-fit gap-1.5" onClick={addWan}>
        <PlusIcon className="size-3.5" />Добавить WAN-аплинк
      </Button>
    </div>
  )
}

// ─── Form state ───────────────────────────────────────────────────────────────

const defaultForm = {
  name: "", type: "exit-node" as ServerType, site: "", country: "RU", asn: "", enabled: true,
  host: "", port: "443", proto: "https" as "http" | "https",
  verifySsl: true, timeout: 10,
  apiPath: "/rest", username: "", password: "", showPassword: false,
  showAdvanced: false, sshPort: 22, winboxPort: 8291, comment: "",
  // home-router extras
  lanSubnet: "",
  wanUplinks: [] as WanUplink[],
}

type FormState = typeof defaultForm
type TestState = "idle" | "testing" | "ok" | "error"
type TypeFilter = "all" | ServerType
type SheetMode = "add" | "edit"

// ════════════════════════════════════════════════════════════════════════════
export default function ServersPage() {
  const { mode, backendUrl, backendStatus } = useDataSource()
  const isLive = mode === "live" && backendStatus === true
  const apiFetch = makeApiFetch(backendUrl)

  const [serverList,   setServerList]   = useState<Server[]>(initialServers)
  const [_backendOk,   setBackendOk]   = useState(false)
  const [search,       setSearch]       = useState("")
  const [typeFilter,   setTypeFilter]   = useState<TypeFilter>("all")
  const [open,         setOpen]         = useState(false)
  const [sheetMode,    setSheetMode]    = useState<SheetMode>("add")
  const [editingId,    setEditingId]    = useState<string | null>(null)
  const [expandedId,   setExpandedId]   = useState<string | null>(null)
  const [form,         setForm]         = useState<FormState>(defaultForm)
  const [testState,    setTestState]    = useState<TestState>("idle")
  const [testMsg,      setTestMsg]      = useState("")
  const [pollingIds,   setPollingIds]   = useState<Set<string>>(new Set())
  const [pollAllBusy,  setPollAllBusy]  = useState(false)

  const set = <K extends keyof FormState>(k: K, v: FormState[K]) =>
    setForm((f) => ({ ...f, [k]: v }))

  // ── load from backend when mode/url changes ───────────────────────────────

  useEffect(() => {
    if (mode !== "live") {
      queueMicrotask(() => {
        setServerList(initialServers)
        setBackendOk(false)
      })
      return
    }
    apiFetch<BackendServer[]>("/api/servers")
      .then(data => {
        setBackendOk(true)
        setServerList(data.map(toFrontend))
      })
      .catch(() => {
        setBackendOk(false)
        setServerList(initialServers)
      })
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [mode, backendUrl])

  // ── actions ──────────────────────────────────────────────────────────────

  function openAdd() {
    setSheetMode("add"); setEditingId(null)
    setForm(defaultForm); setTestState("idle"); setTestMsg("")
    setOpen(true)
  }

  async function openEdit(s: Server) {
    setSheetMode("edit"); setEditingId(s.id)
    setForm({
      ...defaultForm,
      name: s.name, type: s.type, site: s.site, country: s.country ?? "RU",
      asn: s.asn ?? "", enabled: s.status !== "offline", host: s.host,
      comment: s.comment ?? "",
      lanSubnet: s.lanSubnet ?? "",
      wanUplinks: s.wanUplinks ? JSON.parse(JSON.stringify(s.wanUplinks)) : [],
    })
    setTestState("idle"); setTestMsg(""); setOpen(true)

    // Fetch full server details (including credentials) from backend
    if (isLive) {
      try {
        const full = await apiFetch<BackendServer>(`/api/servers/${s.id}`)
        setForm(prev => ({
          ...prev,
          username:  full.username  ?? "",
          password:  full.password  ?? "",
          port:      String(full.port ?? 443),
          proto:     full.useSsl ? "https" : "http",
          verifySsl: full.verifySsl ?? false,
          lanSubnet: full.lanSubnet ?? prev.lanSubnet,
          wanUplinks:
            Array.isArray(full.wanUplinks) && full.wanUplinks.length
              ? JSON.parse(JSON.stringify(full.wanUplinks))
              : prev.wanUplinks,
        }))
      } catch {
        // ignore — user can fill in manually
      }
    }
  }

  async function handleSave() {
    const payload = {
      host:      form.host,
      port:      Number(form.port) || (form.proto === "https" ? 443 : 80),
      username:  form.username,
      password:  form.password,
      useSsl:    form.proto === "https",
      verifySsl: form.verifySsl,
      name:      form.name,
      type:      form.type,
      site:      form.site,
      country:   form.country,
      asn:       form.asn,
      comment:   form.comment,
      enabled:   form.enabled,
      lanSubnet: form.lanSubnet.trim(),
      wanUplinks: form.type === "home-router" ? form.wanUplinks : [],
    }

    if (isLive) {
      try {
        if (sheetMode === "edit" && editingId) {
          const updated = await apiFetch<BackendServer>(
            `/api/servers/${editingId}`,
            { method: "PUT", body: JSON.stringify(payload) },
          )
          setServerList(list => list.map(s => s.id === editingId ? toFrontend(updated) : s))
        } else {
          const created = await apiFetch<BackendServer>(
            "/api/servers",
            { method: "POST", body: JSON.stringify(payload) },
          )
          setServerList(list => [...list, toFrontend(created)])
        }
      } catch (e) {
        console.error("Ошибка сохранения:", e)
      }
    } else {
      // offline mode — update local state only
      if (sheetMode === "edit" && editingId) {
        setServerList(list => list.map(s =>
          s.id === editingId
            ? {
                ...s,
                name: form.name,
                type: form.type,
                site: form.site,
                country: form.country,
                host: form.host,
                asn: form.asn,
                comment: form.comment,
                lanSubnet: form.lanSubnet || undefined,
                wanUplinks: form.type === "home-router" ? form.wanUplinks : undefined,
                status: form.enabled ? (s.status === "offline" ? "online" : s.status) : "offline",
              }
            : s
        ))
      } else {
        setServerList(list => [...list, {
          id: `srv${Date.now()}`, name: form.name || form.host,
          host: form.host, type: form.type, site: form.site,
          country: form.country, asn: form.asn, model: "Unknown", os: "—",
          status: form.enabled ? "online" : "offline",
          enabled: form.enabled, latency: null, sessions: 0,
          comment: form.comment || undefined,
          lanSubnet: form.lanSubnet || undefined,
          wanUplinks: form.type === "home-router" ? form.wanUplinks : undefined,
        }])
      }
    }

    setOpen(false)
  }

  function handleToggleStatus(id: string) {
    setServerList(list => list.map(s =>
      s.id === id ? { ...s, status: s.status === "offline" ? "online" : "offline" } : s
    ))
  }

  async function handleDelete(id: string) {
    if (isLive) {
      try {
        await apiFetch(`/api/servers/${id}`, { method: "DELETE" })
      } catch (e) {
        console.error("Ошибка удаления:", e)
      }
    }
    setServerList(list => list.filter(s => s.id !== id))
  }

  async function handlePoll(id: string) {
    if (!isLive) return
    setPollingIds(p => new Set(p).add(id))
    try {
      await apiFetch(`/api/servers/${id}/poll`, { method: "POST" })
      // Reload full list to get updated status/version
      const data = await apiFetch<BackendServer[]>("/api/servers")
      setServerList(data.map(toFrontend))
    } catch (e) {
      console.error("Poll error:", e)
    } finally {
      setPollingIds(p => { const n = new Set(p); n.delete(id); return n })
    }
  }

  async function handlePollAll() {
    if (!isLive) return
    setPollAllBusy(true)
    try {
      const ids = serverList.map(s => s.id)
      await Promise.all(ids.map(id => apiFetch(`/api/servers/${id}/poll`, { method: "POST" }).catch(() => {})))
      const data = await apiFetch<BackendServer[]>("/api/servers")
      setServerList(data.map(toFrontend))
    } finally {
      setPollAllBusy(false)
    }
  }

  async function handleTest() {
    if (!form.host || !form.username) {
      setTestState("error"); setTestMsg("Заполните Хост и Имя пользователя"); return
    }
    setTestState("testing"); setTestMsg("")
    try {
      const res = await fetch(backendUrl.replace(/\/$/, "") + "/api/servers/test-connection", {
        method:  "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          host:      form.host,
          port:      Number(form.port) || (form.proto === "https" ? 443 : 80),
          useSsl:    form.proto === "https",
          verifySsl: form.verifySsl,
          apiPath:   form.apiPath || "/rest",
          username:  form.username,
          password:  form.password,
        }),
      })
      const data = await res.json() as { success: boolean; message: string }
      if (data.success) {
        setTestState("ok");    setTestMsg(data.message)
      } else {
        setTestState("error"); setTestMsg(data.message)
      }
    } catch {
      setTestState("error")
      setTestMsg(`Не удалось связаться с бекендом — убедитесь, что он запущен на ${backendUrl}`)
    }
  }

  // ── derived ──────────────────────────────────────────────────────────────

  const filtered = useMemo(() => {
    return serverList.filter(sv => {
      if (typeFilter !== "all" && sv.type !== typeFilter) return false
      if (!search) return true
      const q = search.toLowerCase()
      return sv.name.toLowerCase().includes(q) || sv.host.includes(q) || sv.site.toLowerCase().includes(q)
    })
  }, [serverList, search, typeFilter])

  const counts = useMemo(() => ({
    all:          serverList.length,
    "jump-host":  serverList.filter(s => s.type === "jump-host").length,
    "exit-node":  serverList.filter(s => s.type === "exit-node").length,
    "home-router":serverList.filter(s => s.type === "home-router").length,
    online:       serverList.filter(s => s.status === "online").length,
  }), [serverList])

  const tabs: { value: TypeFilter; label: string }[] = [
    { value: "all",          label: "Все"          },
    { value: "jump-host",    label: "JumpHost"      },
    { value: "exit-node",    label: "Exit Node"     },
    { value: "home-router",  label: "Home Router"   },
  ]

  const isHomeRouter = form.type === "home-router"

  // ─────────────────────────────────────────────────────────────────────────

  return (
    <div className="flex flex-col h-full">
      <PageHeader
        crumbs={[{ label: "Управление" }, { label: "Серверы" }]}
        actions={
          <>
            <Button variant="outline" size="sm" onClick={handlePollAll} disabled={!isLive || pollAllBusy}>
              <RefreshCwIcon className={cn("size-4", pollAllBusy && "animate-spin")} />Проверить все
            </Button>
            <Button variant="outline" size="sm"><DownloadIcon className="size-4" />Экспорт</Button>
            <Button size="sm" onClick={openAdd}><PlusIcon className="size-4" />Добавить сервер</Button>
          </>
        }
      />

      <div className="flex-1 overflow-y-auto p-6">
        <div className="flex flex-col gap-5">

          {/* Stats */}
          <div className="grid grid-cols-2 sm:grid-cols-4 gap-4">
            {[
              { label: "Всего серверов",  value: counts.all,          icon: <ServerIcon  className="size-4 text-muted-foreground" /> },
              { label: "Онлайн",          value: counts.online,        icon: <CheckCircleIcon className="size-4 text-emerald-500" /> },
              { label: "JH + Exit Node",  value: counts["jump-host"] + counts["exit-node"], icon: <NetworkIcon className="size-4 text-violet-400" /> },
              { label: "Home Router",     value: counts["home-router"],icon: <HomeIcon    className="size-4 text-emerald-400" /> },
            ].map(s => (
              <Card key={s.label}>
                <CardContent className="px-5 py-4 flex items-start justify-between">
                  <div>
                    <p className="text-sm text-muted-foreground">{s.label}</p>
                    <p className="text-2xl font-semibold tabular-nums mt-0.5">{s.value}</p>
                  </div>
                  <div className="mt-0.5">{s.icon}</div>
                </CardContent>
              </Card>
            ))}
          </div>

          {/* Table */}
          <Card>
            <div className="flex items-center gap-3 px-5 py-3 border-b flex-wrap">
              <div className="flex items-center gap-1 rounded-md border border-border bg-muted/40 p-0.5">
                {tabs.map(tab => (
                  <button key={tab.value} onClick={() => setTypeFilter(tab.value)}
                    className={cn(
                      "flex items-center gap-1.5 rounded px-3 py-1 text-sm transition-colors",
                      typeFilter === tab.value ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground",
                    )}>
                    {tab.label}
                    <span className="text-xs tabular-nums opacity-60">
                      {tab.value === "all" ? counts.all : counts[tab.value as ServerType]}
                    </span>
                  </button>
                ))}
              </div>
              <div className="flex items-center gap-2 h-8 px-3 border border-input rounded-md bg-background min-w-[220px]">
                <SearchIcon className="size-3.5 text-muted-foreground shrink-0" />
                <input className="flex-1 bg-transparent outline-none placeholder:text-muted-foreground text-sm"
                  placeholder="Поиск по имени, хосту…" value={search} onChange={e => setSearch(e.target.value)} />
              </div>
              <span className="text-sm text-muted-foreground ml-auto">{filtered.length} серверов</span>
            </div>

            <div className="overflow-x-auto">
              <table className="w-full text-sm">
                <thead>
                  <tr className="border-b border-border text-xs text-muted-foreground">
                    <th className="text-left font-medium px-5 py-3">Имя / Хост</th>
                    <th className="text-left font-medium px-4 py-3">Тип</th>
                    <th className="text-left font-medium px-4 py-3">Модель</th>
                    <th className="text-left font-medium px-4 py-3">RouterOS</th>
                    <th className="text-left font-medium px-4 py-3">Площадка</th>
                    <th className="text-left font-medium px-4 py-3">WAN / LAN</th>
                    <th className="text-right font-medium px-4 py-3">Задержка</th>
                    <th className="text-left font-medium px-4 py-3">Статус</th>
                    <th className="w-10 px-3 py-3" />
                  </tr>
                </thead>
                <tbody className="divide-y divide-border">
                  {filtered.map(s => {
                    const isExpanded = expandedId === s.id
                    const ver = rosVer(s.os)
                    return (
                      <Fragment key={s.id}>
                        <tr
                          className={cn(
                            "hover:bg-muted/40 transition-colors cursor-pointer",
                            isExpanded && "bg-muted/30",
                          )}
                          onClick={() => setExpandedId(prev => prev === s.id ? null : s.id)}
                        >
                          {/* Expand chevron + name */}
                          <td className="px-5 py-3">
                            <div className="flex items-start gap-2">
                              {isExpanded
                                ? <ChevronDownIcon  className="size-3.5 mt-0.5 shrink-0 text-muted-foreground" />
                                : <ChevronRightIcon className="size-3.5 mt-0.5 shrink-0 text-muted-foreground/40" />}
                              <div className="min-w-0">
                                <p className="font-medium truncate">{s.name}</p>
                                <p className="text-xs font-mono text-muted-foreground">{s.host}</p>
                                {s.ipv6Address && (
                                  <p className="text-[10px] font-mono text-sky-500/70 truncate max-w-[150px]" title={s.ipv6Address}>
                                    {s.ipv6Address}
                                  </p>
                                )}
                              </div>
                            </div>
                          </td>
                          <td className="px-4 py-3"><TypeBadge type={s.type} /></td>
                          <td className="px-4 py-3 text-muted-foreground text-xs">{s.model}</td>
                          <td className="px-4 py-3"><RosBadge os={s.os} /></td>
                          <td className="px-4 py-3">
                            <div className="flex items-center gap-1.5">
                              <Flag code={s.country} />
                              <span className="font-medium">{s.site}</span>
                            </div>
                          </td>
                          {/* WAN / LAN column */}
                          <td className="px-4 py-3">
                            {s.type === "home-router" && s.wanUplinks?.length ? (
                              <div className="flex flex-col gap-0.5">
                                {s.wanUplinks.map(w => (
                                  <div key={w.id} className="flex items-center gap-1.5 text-[11px] font-mono">
                                    <WifiIcon className="size-3 text-sky-400 shrink-0" />
                                    <span className="font-semibold text-sky-600 dark:text-sky-400">{w.name}</span>
                                    <span className="text-muted-foreground">{w.isp}</span>
                                    <span className="text-muted-foreground">↓{w.maxDl}↑{w.maxUl}</span>
                                  </div>
                                ))}
                                {s.lanSubnet && (
                                  <div className="text-[10px] font-mono text-muted-foreground mt-0.5">
                                    LAN {s.lanSubnet}
                                  </div>
                                )}
                              </div>
                            ) : (
                              <div className="flex flex-col gap-0.5">
                                {s.wireGuardIfaces && s.wireGuardIfaces.length > 0 && (
                                  <div className="text-[11px] font-mono text-violet-500 dark:text-violet-400 flex items-center gap-1">
                                    <ShieldIcon className="size-3" />
                                    WG: {s.wireGuardIfaces.length} iface · {s.wireGuardIfaces.reduce((n, i) => n + i.peers.length, 0)} peers
                                  </div>
                                )}
                                {s.rpkiEnabled && (
                                  <div className="text-[10px] font-mono text-emerald-600 dark:text-emerald-400">RPKI ✓</div>
                                )}
                                {!s.wireGuardIfaces?.length && !s.rpkiEnabled && (
                                  <span className="text-xs text-muted-foreground">—</span>
                                )}
                              </div>
                            )}
                          </td>
                          <td className={cn("px-4 py-3 font-mono text-right text-sm",
                            s.latency == null ? "text-muted-foreground"
                            : s.latency > 60  ? "text-[var(--status-degraded-fg)]" : "")}>
                            {s.latency == null ? "—" : `${s.latency} мс`}
                          </td>
                          <td className="px-4 py-3"><StatusBadge status={s.status} /></td>
                          <td className="px-3 py-3" onClick={e => e.stopPropagation()}>
                            <DropdownMenu>
                              <DropdownMenuTrigger render={
                                <Button variant="ghost" size="icon" className="size-7">
                                  <MoreHorizontalIcon className="size-4" />
                                </Button>
                              } />
                              <DropdownMenuContent side="bottom" align="end">
                                <DropdownMenuGroup>
                                  <DropdownMenuLabel>{s.name}</DropdownMenuLabel>
                                </DropdownMenuGroup>
                                <DropdownMenuSeparator />
                                <DropdownMenuItem onClick={() => window.open(`https://${s.host}`, "_blank")}>
                                  <ExternalLinkIcon className="size-3.5" />Открыть WebFig
                                </DropdownMenuItem>
                                <DropdownMenuItem onClick={() => openEdit(s)}>
                                  <PencilIcon className="size-3.5" />Редактировать
                                </DropdownMenuItem>
                                {isLive && (
                                  <DropdownMenuItem onClick={() => handlePoll(s.id)} disabled={pollingIds.has(s.id)}>
                                    <RefreshCwIcon className={cn("size-3.5", pollingIds.has(s.id) && "animate-spin")} />
                                    {pollingIds.has(s.id) ? "Опрос…" : "Опросить"}
                                  </DropdownMenuItem>
                                )}
                                <DropdownMenuItem onClick={() => handleToggleStatus(s.id)}>
                                  <PowerIcon className="size-3.5" />
                                  {s.status === "offline" ? "Включить" : "Отключить"}
                                </DropdownMenuItem>
                                <DropdownMenuSeparator />
                                <DropdownMenuItem variant="destructive" onClick={() => handleDelete(s.id)}>
                                  <Trash2Icon className="size-3.5" />Удалить
                                </DropdownMenuItem>
                              </DropdownMenuContent>
                            </DropdownMenu>
                          </td>
                        </tr>

                        {/* ── Expandable detail row ── */}
                        {isExpanded && (
                          <tr className="bg-muted/20">
                            <td colSpan={9} className="px-8 py-5 border-b border-border/50">
                              <div className="flex flex-col gap-5">

                                {/* Snapshot / live data */}
                                <div className="flex items-start justify-between gap-4 flex-wrap">
                                  <div className="flex flex-wrap gap-x-6 gap-y-2 text-xs">
                                    {s.model && s.model !== "—" && (
                                      <span className="text-muted-foreground">Модель: <span className="font-mono text-foreground">{s.model}</span></span>
                                    )}
                                    {s.uptime && (
                                      <span className="text-muted-foreground">Uptime: <span className="font-mono text-foreground">{s.uptime}</span></span>
                                    )}
                                    {s.cpuLoad != null && (
                                      <span className="text-muted-foreground">CPU: <span className={cn("font-mono font-semibold", s.cpuLoad > 80 ? "text-red-400" : s.cpuLoad > 50 ? "text-amber-400" : "text-emerald-400")}>{s.cpuLoad}%</span></span>
                                    )}
                                    {s.asn && (
                                      <span className="text-muted-foreground">ASN: <span className="font-mono text-foreground">{s.asn}</span></span>
                                    )}
                                    {s.ipv6Address && (
                                      <span className="text-muted-foreground">IPv6: <span className="font-mono text-sky-400">{s.ipv6Address}</span></span>
                                    )}
                                    {s.vrfNames?.map(v => (
                                      <span key={v} className="text-muted-foreground">VRF: <span className="font-mono text-foreground">{v}</span></span>
                                    ))}
                                    {s.comment && (
                                      <span className="text-muted-foreground italic">{s.comment}</span>
                                    )}
                                    {s.polledAt && (
                                      <span className="text-muted-foreground/50 text-[11px]">
                                        Опрошен: {new Date(s.polledAt).toLocaleString("ru")}
                                      </span>
                                    )}
                                    {!s.polledAt && (
                                      <span className="text-amber-500/70 text-[11px]">⚠ Ещё не опрашивался</span>
                                    )}
                                  </div>

                                  {isLive && (
                                    <Button
                                      variant="outline" size="sm"
                                      className="h-7 gap-1.5 text-xs shrink-0"
                                      disabled={pollingIds.has(s.id)}
                                      onClick={e => { e.stopPropagation(); handlePoll(s.id) }}
                                    >
                                      <RefreshCwIcon className={cn("size-3.5", pollingIds.has(s.id) && "animate-spin")} />
                                      {pollingIds.has(s.id) ? "Опрос…" : "Опросить сейчас"}
                                    </Button>
                                  )}
                                </div>

                                {/* Feature matrix */}
                                <div>
                                  <div className="flex items-center gap-3 mb-3">
                                    <p className="text-[11px] font-semibold text-muted-foreground uppercase tracking-wider">
                                      Возможности RouterOS
                                    </p>
                                    <RosBadge os={s.os} />
                                    <span className="text-[11px] text-muted-foreground">
                                      {ver >= 715
                                        ? "✓ Актуальная версия — все ключевые фичи доступны"
                                        : ver >= 710
                                          ? "⚠ Рекомендуется обновление до 7.15+"
                                          : s.os !== "—"
                                            ? "✗ Устаревшая версия — требуется обновление"
                                            : "Нет данных — нажмите «Опросить сейчас»"}
                                    </span>
                                  </div>

                                  <div className="grid grid-cols-2 sm:grid-cols-3 xl:grid-cols-5 gap-2">
                                    {ROS_FEATURES.map(f => {
                                      const ok = ver >= f.minVer
                                      return (
                                        <div key={f.name} className={cn(
                                          "flex items-start gap-2 rounded-md border px-3 py-2.5 transition-colors",
                                          ok
                                            ? "border-emerald-500/25 bg-emerald-500/5"
                                            : "border-border/40 bg-background/40 opacity-60",
                                        )}>
                                          {ok
                                            ? <CheckCircleIcon className="size-3.5 text-emerald-500 shrink-0 mt-0.5" />
                                            : <XCircleIcon    className="size-3.5 text-muted-foreground/40 shrink-0 mt-0.5" />}
                                          <div className="min-w-0">
                                            <p className={cn(
                                              "text-xs font-medium leading-tight truncate",
                                              ok ? "text-foreground" : "text-muted-foreground",
                                            )}>
                                              {f.name}
                                            </p>
                                            <p className="text-[10px] text-muted-foreground leading-tight mt-0.5">
                                              {f.label} · {f.desc}
                                            </p>
                                          </div>
                                        </div>
                                      )
                                    })}
                                  </div>
                                </div>
                              </div>
                            </td>
                          </tr>
                        )}
                      </Fragment>
                    )
                  })}
                </tbody>
              </table>
            </div>
          </Card>
        </div>
      </div>

      {/* ══ Sheet: Add / Edit Server ══════════════════════════════════════════ */}
      <Sheet open={open} onOpenChange={setOpen}>
        <SheetContent side="right" className="w-full sm:max-w-lg flex flex-col gap-0 p-0">
          <SheetHeader className="px-6 pt-6 pb-4 border-b shrink-0">
            <SheetTitle>{sheetMode === "edit" ? "Редактировать сервер" : "Новый сервер"}</SheetTitle>
            <SheetDescription>MikroTik RouterOS · Web API (REST)</SheetDescription>
          </SheetHeader>

          <div className="flex-1 overflow-y-auto px-6 py-5 flex flex-col gap-5">

            {/* 1. Основные */}
            <div className="flex flex-col gap-4">
              <SectionTitle>Основные</SectionTitle>

              <Field label="Имя сервера" required hint="Например home-msk-01">
                <Input className="font-mono" placeholder="home-msk-01"
                  value={form.name} onChange={e => set("name", e.target.value)} />
              </Field>

              <Field label="Тип узла" required>
                <SegmentedControl
                  value={form.type}
                  onChange={v => set("type", v)}
                  options={[
                    { value: "home-router", label: "Home Router" },
                    { value: "jump-host",   label: "JumpHost"    },
                    { value: "exit-node",   label: "Exit Node"   },
                  ]}
                />
              </Field>

              <div className="grid grid-cols-2 gap-3">
                <Field label="Площадка" required hint="MSK, SPB, FRA…">
                  <Input className="font-mono uppercase" placeholder="MSK"
                    value={form.site} onChange={e => set("site", e.target.value.toUpperCase())} />
                </Field>
                {!isHomeRouter && (
                  <Field label="ASN" hint="Например AS65001">
                    <Input className="font-mono" placeholder="AS65001"
                      value={form.asn} onChange={e => set("asn", e.target.value)} />
                  </Field>
                )}
                {isHomeRouter && (
                  <Field label="LAN-подсеть" hint="Например 192.168.10.0/24">
                    <Input className="font-mono" placeholder="192.168.10.0/24"
                      value={form.lanSubnet} onChange={e => set("lanSubnet", e.target.value)} />
                  </Field>
                )}
              </div>

              <CountryField value={form.country} onChange={v => set("country", v)} />

              <div className="flex items-center justify-between">
                <span className="text-sm font-medium">Включён</span>
                <Toggle checked={form.enabled} onChange={v => set("enabled", v)} />
              </div>
            </div>

            {/* 2. WAN-аплинки (только для home-router) */}
            {isHomeRouter && (
              <div className="flex flex-col gap-4">
                <SectionTitle>WAN-аплинки</SectionTitle>
                <WanUplinkEditor
                  wans={form.wanUplinks}
                  onChange={wans => set("wanUplinks", wans)}
                />
              </div>
            )}

            {/* 3. Подключение (API) */}
            <div className="flex flex-col gap-4">
              <SectionTitle>Подключение (RouterOS REST API)</SectionTitle>

              <Field label="Хост / IP-адрес" required
                hint={isHomeRouter
                  ? "Управляющий LAN-адрес роутера, например 192.168.10.1"
                  : "Внешний или управляющий IP-адрес роутера"}>
                <Input className="font-mono" placeholder={isHomeRouter ? "192.168.10.1" : "203.0.113.1"}
                  value={form.host} onChange={e => set("host", e.target.value)} />
              </Field>

              <div className="grid grid-cols-2 gap-3">
                <Field label="Протокол">
                  <SegmentedControl
                    value={form.proto}
                    onChange={v => { set("proto", v); set("port", v === "https" ? "443" : "80") }}
                    options={[{ value: "https", label: "HTTPS" }, { value: "http", label: "HTTP" }]}
                  />
                </Field>
                <Field label="Порт" hint="443 / 80">
                  <Input className="font-mono" placeholder="443"
                    value={form.port} onChange={e => set("port", e.target.value)} />
                </Field>
              </div>

              <div className="flex items-center justify-between">
                <div>
                  <p className="text-sm font-medium flex items-center gap-1.5">
                    <ShieldIcon className="size-3.5 text-muted-foreground" />
                    Проверять SSL-сертификат
                  </p>
                  <p className="text-xs text-muted-foreground">Отключить для self-signed сертификатов</p>
                </div>
                <Toggle checked={form.verifySsl} onChange={v => set("verifySsl", v)} />
              </div>

              <Field label="Путь API">
                <Input className="font-mono" placeholder="/rest"
                  value={form.apiPath} onChange={e => set("apiPath", e.target.value)} />
              </Field>

              <div className="rounded-lg border border-border bg-muted/20 px-4 py-3 text-xs text-muted-foreground">
                <p className="font-medium text-foreground mb-1">RouterOS 7.1+ REST API</p>
                <p className="font-mono text-foreground">
                  {form.proto}://{form.host || "host"}:{form.port}{form.apiPath}
                </p>
                {isHomeRouter && (
                  <p className="mt-1 text-amber-600 dark:text-amber-400">
                    ⚠ Home Router доступен только из LAN / через VPN-туннель
                  </p>
                )}
              </div>

              <Field label="Имя пользователя" required hint="Пользователь RouterOS с доступом к API">
                <Input className="font-mono" placeholder="api-user"
                  value={form.username} onChange={e => set("username", e.target.value)} />
              </Field>

              <Field label="Пароль" required>
                <div className="relative">
                  <Input type={form.showPassword ? "text" : "password"}
                    className="font-mono pr-9" placeholder="Пароль пользователя RouterOS"
                    value={form.password} onChange={e => set("password", e.target.value)} />
                  <button type="button"
                    onClick={() => set("showPassword", !form.showPassword)}
                    className="absolute right-2.5 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground">
                    {form.showPassword ? <EyeOffIcon className="size-3.5" /> : <EyeIcon className="size-3.5" />}
                  </button>
                </div>
              </Field>

              <div className="flex flex-col gap-2">
                <Button type="button" variant="outline" size="sm" className="w-fit gap-2"
                  disabled={testState === "testing"} onClick={handleTest}>
                  {testState === "testing"
                    ? <><LoaderCircleIcon className="size-4 animate-spin" />Проверка…</>
                    : <><WifiIcon className="size-4" />Проверить подключение</>}
                </Button>
                {testState === "ok" && (
                  <div className="flex items-start gap-2 rounded-md border border-current/25 px-3 py-2 text-xs"
                    style={{ background: "var(--status-online-bg)", color: "var(--status-online-fg)" }}>
                    <CheckCircleIcon className="size-3.5 shrink-0 mt-0.5" /><span>{testMsg}</span>
                  </div>
                )}
                {testState === "error" && (
                  <div className="flex items-start gap-2 rounded-md border border-current/25 px-3 py-2 text-xs"
                    style={{ background: "var(--status-offline-bg)", color: "var(--status-offline-fg)" }}>
                    <XCircleIcon className="size-3.5 shrink-0 mt-0.5" /><span>{testMsg}</span>
                  </div>
                )}
              </div>
            </div>

            {/* 4. Дополнительно */}
            <div className="flex flex-col gap-4">
              <button type="button" onClick={() => set("showAdvanced", !form.showAdvanced)}
                className="flex items-center gap-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground hover:text-foreground transition-colors">
                {form.showAdvanced ? <ChevronDownIcon className="size-3.5" /> : <ChevronRightIcon className="size-3.5" />}
                Дополнительно
                <div className="flex-1 h-px bg-border" />
              </button>
              {form.showAdvanced && (
                <div className="flex flex-col gap-4">
                  <div className="grid grid-cols-2 gap-3">
                    <Field label="SSH-порт">
                      <Input type="number" className="font-mono" value={form.sshPort}
                        onChange={e => set("sshPort", Number(e.target.value))} />
                    </Field>
                    <Field label="Winbox-порт">
                      <Input type="number" className="font-mono" value={form.winboxPort}
                        onChange={e => set("winboxPort", Number(e.target.value))} />
                    </Field>
                  </div>
                  <Field label="Таймаут соединения, с">
                    <Input type="number" className="font-mono" value={form.timeout}
                      onChange={e => set("timeout", Number(e.target.value))} />
                  </Field>
                  <Field label="Комментарий">
                    <Input placeholder="Описание или заметка" value={form.comment}
                      onChange={e => set("comment", e.target.value)} />
                  </Field>
                </div>
              )}
            </div>

          </div>

          <SheetFooter className="px-6 py-4 border-t shrink-0 flex-row gap-2">
            <SheetClose render={<Button variant="outline" className="flex-1" />}>Отмена</SheetClose>
            <Button className="flex-1" onClick={handleSave}>
              {sheetMode === "edit" ? "Сохранить" : "Добавить сервер"}
            </Button>
          </SheetFooter>
        </SheetContent>
      </Sheet>
    </div>
  )
}
