"use client"

import { useMemo, useState } from "react"
import { PageHeader } from "@/components/page-header"
import { greTunnels, grePools, servers } from "@/lib/data"
import type { GreTunnel, GreStatus, IpsecEncAlg, IpsecAuthAlg, IpsecDhGroup, IkeVersion } from "@/lib/data"
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 { Flag } from "@/components/flag"
import {
  PlusIcon, SearchIcon, RefreshCwIcon, MoreHorizontalIcon,
  LockIcon, LockOpenIcon, ShieldCheckIcon, NetworkIcon,
  EyeIcon, EyeOffIcon, ChevronDownIcon, ChevronRightIcon,
  CodeXmlIcon, PencilIcon, PowerIcon, Trash2Icon, CopyIcon, CheckIcon,
} from "lucide-react"

// ─── label maps ─────────────────────────────────────────────────────────────

const ENC_LABELS: Record<IpsecEncAlg, string>  = { "aes-128": "AES-128", "aes-192": "AES-192", "aes-256": "AES-256" }
const AUTH_LABELS: Record<IpsecAuthAlg, string> = { sha1: "SHA-1", sha256: "SHA-256", sha512: "SHA-512" }
const DH_LABELS: Record<IpsecDhGroup, string>   = {
  modp1024: "DH-2 (1024)", modp2048: "DH-14 (2048)", modp4096: "DH-16 (4096)",
  ecp256: "ECP-256", ecp384: "ECP-384", ecp521: "ECP-521",
}
const IKE_LABELS: Record<IkeVersion, string> = { ikev1: "IKEv1", ikev2: "IKEv2" }

const ENC_ROS: Record<IpsecEncAlg, string>  = { "aes-128": "aes-128-cbc", "aes-192": "aes-192-cbc", "aes-256": "aes-256-cbc" }
const AUTH_ROS: Record<IpsecAuthAlg, string> = { sha1: "sha1", sha256: "sha256", sha512: "sha512" }

const STATUS_MAP: Record<GreStatus, { label: string; dot: string }> = {
  up:       { label: "Up",       dot: "bg-emerald-500" },
  degraded: { label: "Degraded", dot: "bg-amber-500"   },
  down:     { label: "Down",     dot: "bg-red-500"      },
}

const serverById = Object.fromEntries(servers.map((s) => [s.id, s]))
const poolById   = Object.fromEntries(grePools.map((p) => [p.id, p]))

// ─── RouterOS code generator ─────────────────────────────────────────────────

function generateRosCommands(t: GreTunnel): string {
  const lines: string[] = []
  const srv = serverById[t.serverId]

  lines.push(`# Сервер: ${srv?.name ?? t.serverId} (${srv?.host ?? ""})`)
  lines.push(`# Сгенерировано RouterLists · ${new Date().toLocaleDateString("ru")}`)
  lines.push("")

  // GRE interface
  lines.push("# ── GRE-интерфейс ────────────────────────────────────────────")
  const greParts = [
    `/interface gre add`,
    `  name=${t.name}`,
    `  remote-address=${t.remoteAddress}`,
    t.localAddress !== "0.0.0.0" ? `  local-address=${t.localAddress}` : null,
    t.ipsec ? `  ipsec-secret="${t.ipsec.secret}"` : null,
    `  mtu=${t.mtu}`,
    t.keepaliveInterval > 0 ? `  keepalive=${t.keepaliveInterval}s,${t.keepaliveRetries}` : `  keepalive=0`,
    `  dscp=${t.dscp}`,
    `  clamp-tcp-mss=${t.clampTcpMss ? "yes" : "no"}`,
    `  allow-fast-path=${t.allowFastPath ? "yes" : "no"}`,
    t.comment ? `  comment="${t.comment}"` : null,
    !t.enabled ? `  disabled=yes` : null,
  ].filter(Boolean) as string[]
  lines.push(greParts.join(" \\\n"))

  // Inner IP
  lines.push("")
  lines.push("# ── Внутренний IP ────────────────────────────────────────────")
  lines.push(`/ip address add \\`)
  lines.push(`  address=${t.localInnerIp} \\`)
  lines.push(`  interface=${t.name}`)

  // IPsec manual equivalent
  if (t.ipsec) {
    const ikeMode = t.ipsec.ikeVersion === "ikev2" ? "ike2" : "ike1"
    const pfsGroup = t.ipsec.pfs ? t.ipsec.dhGroup : "none"

    lines.push("")
    lines.push("# ── IPsec (авто через ipsec-secret; ручной эквивалент) ───────")
    lines.push("")
    lines.push(`/ip ipsec peer add \\`)
    lines.push(`  name=${t.name} \\`)
    lines.push(`  address=${t.remoteAddress} \\`)
    lines.push(`  exchange-mode=${ikeMode} \\`)
    lines.push(`  auth-method=pre-shared-key \\`)
    lines.push(`  secret="${t.ipsec.secret}"`)
    lines.push("")
    lines.push(`/ip ipsec proposal add \\`)
    lines.push(`  name=${t.name} \\`)
    lines.push(`  enc-algorithms=${ENC_ROS[t.ipsec.encAlg]} \\`)
    lines.push(`  auth-algorithms=${AUTH_ROS[t.ipsec.authAlg]} \\`)
    lines.push(`  pfs-group=${pfsGroup} \\`)
    lines.push(`  lifetime=${t.ipsec.lifetime}`)
    lines.push("")
    lines.push(`/ip ipsec policy add \\`)
    lines.push(`  src-address=${t.localAddress !== "0.0.0.0" ? t.localAddress + "/32" : "0.0.0.0/0"} \\`)
    lines.push(`  dst-address=${t.remoteAddress}/32 \\`)
    lines.push(`  proposal=${t.name} \\`)
    lines.push(`  tunnel=yes`)
  }

  return lines.join("\n")
}

// ─── small ui helpers ────────────────────────────────────────────────────────

function TunnelStatus({ status }: { status: GreStatus }) {
  const s = STATUS_MAP[status]
  return (
    <span className="inline-flex items-center gap-1.5 text-sm">
      <span className={`size-1.5 rounded-full ${s.dot}`} />
      {s.label}
    </span>
  )
}

function IpsecBadge({ secured }: { secured: boolean }) {
  return secured ? (
    <span className="inline-flex items-center gap-1 text-xs font-medium border rounded px-2 py-0.5 bg-emerald-500/10 text-emerald-400 border-emerald-500/20">
      <LockIcon className="size-3" /> IPsec
    </span>
  ) : (
    <span className="inline-flex items-center gap-1 text-xs font-medium border rounded px-2 py-0.5 bg-muted text-muted-foreground border-border">
      <LockOpenIcon className="size-3" /> Открытый
    </span>
  )
}

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={`relative inline-flex h-5 w-9 shrink-0 rounded-full border-2 border-transparent transition-colors ${checked ? "bg-primary" : "bg-input"}`}
    >
      <span className={`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-1">
      <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={`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>
  )
}

// ─── default form states ─────────────────────────────────────────────────────

const defaultTunnelForm = {
  name: "", serverId: "", localAddress: "", remoteAddress: "",
  poolId: "", localInnerIp: "", remoteInnerIp: "", comment: "", enabled: true,
  ipsecEnabled: false, ipsecSecret: "", ipsecShowSecret: false,
  ipsecIkeVersion: "ikev2" as IkeVersion,
  ipsecEncAlg: "aes-256" as IpsecEncAlg,
  ipsecAuthAlg: "sha256" as IpsecAuthAlg,
  ipsecDhGroup: "modp2048" as IpsecDhGroup,
  ipsecLifetime: "1d 00:00:00", ipsecPfs: true,
  mtu: 1476, keepaliveInterval: 10, keepaliveRetries: 10,
  dscp: "inherit", clampTcpMss: true, allowFastPath: true,
  showAdvanced: false,
}

const defaultPoolForm = { name: "", cidr: "", comment: "" }

type TabFilter = "all" | "up" | "ipsec" | "plain"
type PageTab   = "tunnels" | "pools"

// ════════════════════════════════════════════════════════════════════════════
export default function GrePage() {
  const [pageTab,   setPageTab]   = useState<PageTab>("tunnels")
  const [tabFilter, setTabFilter] = useState<TabFilter>("all")
  const [search,    setSearch]    = useState("")

  const [tunnelOpen,      setTunnelOpen]      = useState(false)
  const [poolOpen,        setPoolOpen]        = useState(false)
  const [codePreviewTunnel, setCodePreviewTunnel] = useState<GreTunnel | null>(null)
  const [copied,          setCopied]          = useState(false)

  const [tForm, setTForm] = useState(defaultTunnelForm)
  const [pForm, setPForm] = useState(defaultPoolForm)

  const setT = <K extends keyof typeof defaultTunnelForm>(k: K, v: (typeof defaultTunnelForm)[K]) =>
    setTForm((f) => ({ ...f, [k]: v }))

  const filtered = useMemo(() => {
    return greTunnels.filter((t) => {
      if (tabFilter === "up"    && t.status !== "up") return false
      if (tabFilter === "ipsec" && !t.ipsec)          return false
      if (tabFilter === "plain" && t.ipsec)           return false
      if (!search) return true
      const q = search.toLowerCase()
      return (
        t.name.toLowerCase().includes(q) ||
        t.remoteAddress.includes(q)      ||
        t.localInnerIp.includes(q)       ||
        serverById[t.serverId]?.name.toLowerCase().includes(q)
      )
    })
  }, [tabFilter, search])

  const upCount    = greTunnels.filter((t) => t.status === "up").length
  const ipsecCount = greTunnels.filter((t) => t.ipsec).length

  const tunnelTabs: { value: TabFilter; label: string; count: number }[] = [
    { value: "all",   label: "Все",       count: greTunnels.length },
    { value: "up",    label: "Активные",  count: upCount           },
    { value: "ipsec", label: "С IPsec",   count: ipsecCount        },
    { value: "plain", label: "Без IPsec", count: greTunnels.length - ipsecCount },
  ]

  function handleCopy(code: string) {
    navigator.clipboard.writeText(code).then(() => {
      setCopied(true)
      setTimeout(() => setCopied(false), 2000)
    })
  }

  return (
    <div className="flex flex-col h-full">
      <PageHeader
        crumbs={[{ label: "Управление" }, { label: "GRE-туннели" }]}
        actions={
          <>
            <Button variant="outline" size="sm"><RefreshCwIcon className="size-4" />Обновить статус</Button>
            <Button size="sm" onClick={() => { setTForm(defaultTunnelForm); setTunnelOpen(true) }}>
              <PlusIcon className="size-4" />Добавить туннель
            </Button>
          </>
        }
      />

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

          {/* Legacy banner */}
          <div className="flex items-start gap-3 rounded-lg bg-amber-500/5 border border-amber-500/20 px-4 py-3 text-sm">
            <ShieldCheckIcon className="size-5 text-amber-500 shrink-0 mt-0.5" />
            <div>
              <p className="font-medium text-amber-600 dark:text-amber-400">
                В RouterOS 7.x рекомендуется использовать WireGuard вместо GRE+IPsec
              </p>
              <p className="text-muted-foreground text-xs mt-0.5">
                WireGuard проще в настройке, обеспечивает лучшую производительность и современную криптографию (ChaCha20-Poly1305).
                GRE-туннели остаются поддерживаемыми, но WireGuard — предпочтительный выбор для новых развёртываний.
              </p>
            </div>
          </div>

          {/* Stats */}
          <div className="grid grid-cols-4 gap-4">
            {[
              { label: "Всего туннелей",  value: greTunnels.length, icon: <NetworkIcon     className="size-4 text-muted-foreground" /> },
              { label: "Активно",         value: upCount,           icon: <ShieldCheckIcon className="size-4 text-emerald-500" />     },
              { label: "Защищены IPsec",  value: ipsecCount,        icon: <LockIcon        className="size-4 text-violet-400" />      },
              { label: "IP-пулов",        value: grePools.length,   icon: <NetworkIcon     className="size-4 text-sky-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>

          {/* Page tabs */}
          <div className="flex items-center gap-1 border-b">
            {(["tunnels", "pools"] as PageTab[]).map((tab) => (
              <button key={tab} onClick={() => setPageTab(tab)}
                className={`px-4 py-2 text-sm font-medium border-b-2 transition-colors -mb-px ${pageTab === tab ? "border-foreground text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"}`}>
                {tab === "tunnels" ? "Туннели" : "IP-пулы"}
              </button>
            ))}
          </div>

          {/* ── Tunnels ── */}
          {pageTab === "tunnels" && (
            <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">
                  {tunnelTabs.map((t) => (
                    <button key={t.value} onClick={() => setTabFilter(t.value)}
                      className={`flex items-center gap-1.5 rounded px-3 py-1 text-sm transition-colors ${tabFilter === t.value ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`}>
                      {t.label}
                      <span className="text-xs tabular-nums opacity-60">{t.count}</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="Поиск по имени, IP…" 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">Внутренний IP</th>
                      <th className="text-left font-medium px-4 py-3">Пул</th>
                      <th className="text-left font-medium px-4 py-3">IPsec</th>
                      <th className="text-left font-medium px-4 py-3">Шифрование</th>
                      <th className="text-center font-medium px-4 py-3">MTU</th>
                      <th className="text-left font-medium px-4 py-3">Keepalive</th>
                      <th className="text-left font-medium px-4 py-3">Статус</th>
                      <th className="w-20 px-3 py-3" />
                    </tr>
                  </thead>
                  <tbody className="divide-y divide-border">
                    {filtered.map((t) => {
                      const srv  = serverById[t.serverId]
                      const pool = poolById[t.poolId]
                      return (
                        <tr key={t.id} className="hover:bg-muted/40 transition-colors">
                          <td className="px-5 py-3">
                            <p className="font-medium font-mono text-[13px]">{t.name}</p>
                            <p className="text-xs text-muted-foreground mt-0.5 flex items-center gap-1">
                              {srv && <Flag code={srv.country} />}
                              {srv?.name ?? t.serverId}
                            </p>
                          </td>
                          <td className="px-4 py-3">
                            <p className="font-mono text-xs">
                              {t.localAddress === "0.0.0.0" ? <span className="text-muted-foreground">авто</span> : t.localAddress}
                            </p>
                            <p className="font-mono text-xs text-muted-foreground">→ {t.remoteAddress}</p>
                          </td>
                          <td className="px-4 py-3">
                            <p className="font-mono text-xs">{t.localInnerIp}</p>
                            <p className="font-mono text-xs text-muted-foreground">{t.remoteInnerIp}</p>
                          </td>
                          <td className="px-4 py-3">
                            <span className="text-xs text-muted-foreground font-mono">{pool?.name ?? "—"}</span>
                          </td>
                          <td className="px-4 py-3"><IpsecBadge secured={!!t.ipsec} /></td>
                          <td className="px-4 py-3">
                            {t.ipsec ? (
                              <div className="flex flex-col gap-0.5">
                                <span className="text-xs font-mono">{ENC_LABELS[t.ipsec.encAlg]} / {AUTH_LABELS[t.ipsec.authAlg]}</span>
                                <span className="text-xs text-muted-foreground font-mono">
                                  {DH_LABELS[t.ipsec.dhGroup].split(" ")[0]} · {IKE_LABELS[t.ipsec.ikeVersion]}{t.ipsec.pfs && " · PFS"}
                                </span>
                              </div>
                            ) : <span className="text-xs text-muted-foreground">—</span>}
                          </td>
                          <td className="px-4 py-3 text-center font-mono text-xs">{t.mtu}</td>
                          <td className="px-4 py-3 font-mono text-xs text-muted-foreground">
                            {t.keepaliveInterval === 0 ? "откл." : `${t.keepaliveInterval}с / ${t.keepaliveRetries}`}
                          </td>
                          <td className="px-4 py-3"><TunnelStatus status={t.status} /></td>

                          {/* actions */}
                          <td className="px-3 py-3">
                            <div className="flex items-center gap-1 justify-end">
                              {/* Code preview button */}
                              <Button
                                variant="ghost" size="icon" className="size-7"
                                title="Предпросмотр кода RouterOS"
                                onClick={() => setCodePreviewTunnel(t)}
                              >
                                <CodeXmlIcon className="size-3.5" />
                              </Button>

                              {/* Actions dropdown */}
                              <DropdownMenu>
                                <DropdownMenuTrigger render={
                                  <Button variant="ghost" size="icon" className="size-7">
                                    <MoreHorizontalIcon className="size-4" />
                                  </Button>
                                } />
                                <DropdownMenuContent side="bottom" align="end">
                                  <DropdownMenuGroup>
                                    <DropdownMenuLabel>{t.name}</DropdownMenuLabel>
                                  </DropdownMenuGroup>
                                  <DropdownMenuSeparator />
                                  <DropdownMenuItem onClick={() => setCodePreviewTunnel(t)}>
                                    <CodeXmlIcon className="size-4" /> Просмотр кода
                                  </DropdownMenuItem>
                                  <DropdownMenuItem>
                                    <PencilIcon className="size-4" /> Редактировать
                                  </DropdownMenuItem>
                                  <DropdownMenuSeparator />
                                  <DropdownMenuItem>
                                    <PowerIcon className="size-4" />
                                    {t.enabled ? "Выключить" : "Включить"}
                                  </DropdownMenuItem>
                                  <DropdownMenuSeparator />
                                  <DropdownMenuItem variant="destructive">
                                    <Trash2Icon className="size-4" /> Удалить туннель
                                  </DropdownMenuItem>
                                </DropdownMenuContent>
                              </DropdownMenu>
                            </div>
                          </td>
                        </tr>
                      )
                    })}
                  </tbody>
                </table>
              </div>
            </Card>
          )}

          {/* ── IP Pools ── */}
          {pageTab === "pools" && (
            <Card>
              <div className="flex items-center justify-between px-5 py-3 border-b">
                <span className="text-sm text-muted-foreground">{grePools.length} пула</span>
                <Button size="sm" variant="outline" onClick={() => { setPForm(defaultPoolForm); setPoolOpen(true) }}>
                  <PlusIcon className="size-4" />Добавить пул
                </Button>
              </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">Диапазон CIDR</th>
                      <th className="text-right font-medium px-4 py-3">Назначено /30</th>
                      <th className="text-right font-medium px-4 py-3">Доступно /30</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="w-10 px-3 py-3" />
                    </tr>
                  </thead>
                  <tbody className="divide-y divide-border">
                    {grePools.map((pool) => {
                      const pct = Math.round((pool.allocated / pool.total) * 100)
                      return (
                        <tr key={pool.id} className="hover:bg-muted/40 transition-colors">
                          <td className="px-5 py-3 font-mono text-[13px] font-medium">{pool.name}</td>
                          <td className="px-4 py-3 font-mono text-xs">{pool.cidr}</td>
                          <td className="px-4 py-3 text-right tabular-nums">{pool.allocated}</td>
                          <td className="px-4 py-3 text-right tabular-nums text-muted-foreground">{pool.total - pool.allocated}</td>
                          <td className="px-4 py-3 min-w-[140px]">
                            <div className="flex items-center gap-2">
                              <div className="flex-1 h-1.5 rounded-full bg-muted overflow-hidden">
                                <div className={`h-full rounded-full ${pct > 80 ? "bg-amber-500" : "bg-emerald-500"}`} style={{ width: `${pct}%` }} />
                              </div>
                              <span className="text-xs text-muted-foreground tabular-nums w-8 text-right">{pct}%</span>
                            </div>
                          </td>
                          <td className="px-4 py-3 text-muted-foreground text-xs">{pool.comment}</td>
                          <td className="px-3 py-3">
                            <DropdownMenu>
                              <DropdownMenuTrigger render={
                                <Button variant="ghost" size="icon" className="size-7">
                                  <MoreHorizontalIcon className="size-4" />
                                </Button>
                              } />
                              <DropdownMenuContent side="bottom" align="end">
                                <DropdownMenuItem><PencilIcon className="size-4" /> Редактировать</DropdownMenuItem>
                                <DropdownMenuSeparator />
                                <DropdownMenuItem variant="destructive"><Trash2Icon className="size-4" /> Удалить пул</DropdownMenuItem>
                              </DropdownMenuContent>
                            </DropdownMenu>
                          </td>
                        </tr>
                      )
                    })}
                  </tbody>
                </table>
              </div>

              <div className="border-t px-5 py-4">
                <p className="text-xs font-medium text-muted-foreground mb-3">Назначения по пулам</p>
                <div className="flex flex-col gap-3">
                  {grePools.map((pool) => {
                    const poolTunnels = greTunnels.filter((t) => t.poolId === pool.id)
                    return (
                      <div key={pool.id}>
                        <p className="text-xs font-mono font-medium mb-1.5">{pool.name}</p>
                        <div className="flex flex-wrap gap-2">
                          {poolTunnels.map((t) => (
                            <div key={t.id} className="flex items-center gap-2 border border-border rounded-md px-3 py-1.5 bg-muted/30 text-xs">
                              <span className={`size-1.5 rounded-full ${STATUS_MAP[t.status].dot}`} />
                              <span className="font-mono font-medium">{t.name}</span>
                              <span className="text-muted-foreground">{t.localInnerIp} ↔ {t.remoteInnerIp}</span>
                              {t.ipsec && <LockIcon className="size-3 text-emerald-400" />}
                            </div>
                          ))}
                        </div>
                      </div>
                    )
                  })}
                </div>
              </div>
            </Card>
          )}

          {/* RouterOS reference */}
          <Card>
            <CardContent className="px-5 py-4">
              <p className="text-xs font-medium text-muted-foreground mb-3">RouterOS 7.20+ — параметры GRE-интерфейса</p>
              <div className="grid grid-cols-2 gap-x-8 gap-y-1 text-xs font-mono">
                {[
                  ["/interface gre add", ""],
                  ["  name=",            "имя интерфейса"],
                  ["  remote-address=",  "IP удалённого конца (обязателен)"],
                  ["  local-address=",   "0.0.0.0 = авто"],
                  ["  ipsec-secret=",    "PSK → auto peer+policy+proposal"],
                  ["  mtu=",             "по умолчанию 1476"],
                  ["  keepalive=",       "10s,10 (интервал,попытки)"],
                  ["  dscp=",            "inherit | 0-63"],
                  ["  clamp-tcp-mss=",   "yes | no"],
                  ["  allow-fast-path=", "yes | no"],
                  ["/ip address add",    ""],
                  ["  address=x.x.x.x/30", "внутренний IP туннеля"],
                  ["  interface=<name>", ""],
                ].map(([cmd, desc], i) => (
                  <div key={i} className="flex gap-2 py-0.5">
                    <span className="text-foreground/70 shrink-0">{cmd}</span>
                    {desc && <span className="text-muted-foreground"># {desc}</span>}
                  </div>
                ))}
              </div>
            </CardContent>
          </Card>
        </div>
      </div>

      {/* ══ Sheet: Code Preview ════════════════════════════════════════════════ */}
      <Sheet open={!!codePreviewTunnel} onOpenChange={(open) => { if (!open) setCodePreviewTunnel(null) }}>
        <SheetContent side="right" className="w-full sm:max-w-2xl flex flex-col gap-0 p-0">
          {codePreviewTunnel && (() => {
            const code = generateRosCommands(codePreviewTunnel)
            return (
              <>
                <SheetHeader className="px-6 pt-6 pb-4 border-b shrink-0">
                  <div className="flex items-start justify-between gap-4">
                    <div>
                      <SheetTitle className="font-mono">{codePreviewTunnel.name}</SheetTitle>
                      <SheetDescription>Команды RouterOS 7.20+ для создания туннеля</SheetDescription>
                    </div>
                    <Button
                      variant="outline" size="sm"
                      className="shrink-0 gap-1.5"
                      onClick={() => handleCopy(code)}
                    >
                      {copied
                        ? <><CheckIcon className="size-3.5 text-emerald-500" /> Скопировано</>
                        : <><CopyIcon  className="size-3.5" /> Копировать</>}
                    </Button>
                  </div>
                </SheetHeader>

                <div className="flex-1 overflow-y-auto">
                  {/* meta strip */}
                  <div className="flex flex-wrap gap-3 px-6 py-3 border-b bg-muted/30 text-xs">
                    <span className="flex items-center gap-1.5">
                      <span className={`size-1.5 rounded-full ${STATUS_MAP[codePreviewTunnel.status].dot}`} />
                      {STATUS_MAP[codePreviewTunnel.status].label}
                    </span>
                    <span className="text-muted-foreground">·</span>
                    <span>{serverById[codePreviewTunnel.serverId]?.name}</span>
                    <span className="text-muted-foreground">·</span>
                    <span className="font-mono">{codePreviewTunnel.localAddress === "0.0.0.0" ? "авто" : codePreviewTunnel.localAddress} → {codePreviewTunnel.remoteAddress}</span>
                    {codePreviewTunnel.ipsec && (
                      <>
                        <span className="text-muted-foreground">·</span>
                        <span className="flex items-center gap-1 text-emerald-400"><LockIcon className="size-3" /> IPsec {IKE_LABELS[codePreviewTunnel.ipsec.ikeVersion]}</span>
                      </>
                    )}
                  </div>

                  {/* code block */}
                  <pre className="px-6 py-5 text-xs font-mono leading-relaxed text-foreground/90 whitespace-pre overflow-x-auto select-all">
                    {code.split("\n").map((line, i) => {
                      const isComment  = line.startsWith("#")
                      const isSection  = isComment && line.includes("──")
                      const isKey      = /^\s+[a-z]/.test(line)
                      return (
                        <span key={i} className={
                          isSection ? "text-muted-foreground/60"
                          : isComment ? "text-muted-foreground"
                          : isKey    ? "text-sky-400/90"
                          : "text-foreground"
                        }>
                          {line}
                          {"\n"}
                        </span>
                      )
                    })}
                  </pre>
                </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 gap-1.5" onClick={() => handleCopy(code)}>
                    {copied ? <CheckIcon className="size-4" /> : <CopyIcon className="size-4" />}
                    {copied ? "Скопировано" : "Копировать команды"}
                  </Button>
                </SheetFooter>
              </>
            )
          })()}
        </SheetContent>
      </Sheet>

      {/* ══ Sheet: Add Tunnel ══════════════════════════════════════════════════ */}
      <Sheet open={tunnelOpen} onOpenChange={setTunnelOpen}>
        <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>Новый GRE-туннель</SheetTitle>
            <SheetDescription>RouterOS 7.20+ · /interface gre add</SheetDescription>
          </SheetHeader>

          <div className="flex-1 overflow-y-auto px-6 py-5 flex flex-col gap-5">
            <div className="flex flex-col gap-4">
              <SectionTitle>Основные</SectionTitle>
              <Field label="Имя интерфейса" required hint="Только латиница, цифры и дефис, например gre-msk-spb">
                <Input className="font-mono" placeholder="gre-msk-spb" value={tForm.name} onChange={(e) => setT("name", e.target.value)} />
              </Field>
              <Field label="Сервер (MikroTik)" required>
                <select value={tForm.serverId} onChange={(e) => setT("serverId", e.target.value)}
                  className="h-8 w-full rounded-lg border border-input bg-transparent px-2.5 text-sm outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50">
                  <option value="" disabled>Выбрать сервер…</option>
                  {servers.map((s) => <option key={s.id} value={s.id}>{s.name} ({s.site})</option>)}
                </select>
              </Field>
              <Field label="Комментарий">
                <Input placeholder="Описание туннеля" value={tForm.comment} onChange={(e) => setT("comment", e.target.value)} />
              </Field>
              <div className="flex items-center justify-between">
                <span className="text-sm font-medium">Включён</span>
                <Toggle checked={tForm.enabled} onChange={(v) => setT("enabled", v)} />
              </div>
            </div>

            <div className="flex flex-col gap-4">
              <SectionTitle>Эндпоинты</SectionTitle>
              <Field label="Локальный адрес" hint="Оставьте пустым или 0.0.0.0 для автоопределения">
                <Input className="font-mono" placeholder="0.0.0.0" value={tForm.localAddress} onChange={(e) => setT("localAddress", e.target.value)} />
              </Field>
              <Field label="Удалённый адрес" required hint="Внешний IP удалённого MikroTik">
                <Input className="font-mono" placeholder="203.0.113.1" value={tForm.remoteAddress} onChange={(e) => setT("remoteAddress", e.target.value)} />
              </Field>
            </div>

            <div className="flex flex-col gap-4">
              <SectionTitle>Внутренний IP</SectionTitle>
              <Field label="IP-пул" required hint="Из какого пула выделяется /30-блок">
                <select value={tForm.poolId} onChange={(e) => setT("poolId", e.target.value)}
                  className="h-8 w-full rounded-lg border border-input bg-transparent px-2.5 text-sm outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50">
                  <option value="" disabled>Выбрать пул…</option>
                  {grePools.map((p) => <option key={p.id} value={p.id}>{p.name} ({p.cidr}) — свободно {p.total - p.allocated} блоков</option>)}
                </select>
              </Field>
              <div className="grid grid-cols-2 gap-3">
                <Field label="Локальный IP" required hint="/ip address на этом конце">
                  <Input className="font-mono" placeholder="10.200.0.1/30" value={tForm.localInnerIp} onChange={(e) => setT("localInnerIp", e.target.value)} />
                </Field>
                <Field label="Удалённый IP" required hint="/ip address на другом конце">
                  <Input className="font-mono" placeholder="10.200.0.2/30" value={tForm.remoteInnerIp} onChange={(e) => setT("remoteInnerIp", e.target.value)} />
                </Field>
              </div>
            </div>

            <div className="flex flex-col gap-4">
              <SectionTitle>IPsec</SectionTitle>
              <div className="flex items-center justify-between">
                <div>
                  <p className="text-sm font-medium">Включить IPsec</p>
                  <p className="text-xs text-muted-foreground">RouterOS автоматически создаст peer, policy и proposal</p>
                </div>
                <Toggle checked={tForm.ipsecEnabled} onChange={(v) => setT("ipsecEnabled", v)} />
              </div>

              {tForm.ipsecEnabled && (
                <div className="flex flex-col gap-4 pl-4 border-l-2 border-emerald-500/30">
                  <Field label="Пароль (PSK)" required hint="ipsec-secret — pre-shared key для автоматического IKE">
                    <div className="relative">
                      <Input type={tForm.ipsecShowSecret ? "text" : "password"} className="font-mono pr-9"
                        placeholder="Минимум 8 символов" value={tForm.ipsecSecret} onChange={(e) => setT("ipsecSecret", e.target.value)} />
                      <button type="button" onClick={() => setT("ipsecShowSecret", !tForm.ipsecShowSecret)}
                        className="absolute right-2.5 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground">
                        {tForm.ipsecShowSecret ? <EyeOffIcon className="size-3.5" /> : <EyeIcon className="size-3.5" />}
                      </button>
                    </div>
                  </Field>
                  <Field label="IKE-версия">
                    <SegmentedControl value={tForm.ipsecIkeVersion} onChange={(v) => setT("ipsecIkeVersion", v)}
                      options={[{ value: "ikev1", label: "IKEv1" }, { value: "ikev2", label: "IKEv2 (рек.)" }]} />
                  </Field>
                  <div className="grid grid-cols-2 gap-3">
                    <Field label="Шифрование">
                      <select value={tForm.ipsecEncAlg} onChange={(e) => setT("ipsecEncAlg", e.target.value as IpsecEncAlg)}
                        className="h-8 w-full rounded-lg border border-input bg-transparent px-2.5 text-sm outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50">
                        {(Object.entries(ENC_LABELS) as [IpsecEncAlg, string][]).map(([v, l]) => <option key={v} value={v}>{l}</option>)}
                      </select>
                    </Field>
                    <Field label="Хеш-алгоритм">
                      <select value={tForm.ipsecAuthAlg} onChange={(e) => setT("ipsecAuthAlg", e.target.value as IpsecAuthAlg)}
                        className="h-8 w-full rounded-lg border border-input bg-transparent px-2.5 text-sm outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50">
                        {(Object.entries(AUTH_LABELS) as [IpsecAuthAlg, string][]).map(([v, l]) => <option key={v} value={v}>{l}</option>)}
                      </select>
                    </Field>
                  </div>
                  <Field label="DH-группа" hint="Группа Диффи-Хеллмана для обмена ключами">
                    <select value={tForm.ipsecDhGroup} onChange={(e) => setT("ipsecDhGroup", e.target.value as IpsecDhGroup)}
                      className="h-8 w-full rounded-lg border border-input bg-transparent px-2.5 text-sm outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50">
                      {(Object.entries(DH_LABELS) as [IpsecDhGroup, string][]).map(([v, l]) => <option key={v} value={v}>{l}</option>)}
                    </select>
                  </Field>
                  <div className="grid grid-cols-2 gap-3">
                    <Field label="Срок жизни SA" hint="Формат: 1d 00:00:00">
                      <Input className="font-mono" value={tForm.ipsecLifetime} onChange={(e) => setT("ipsecLifetime", e.target.value)} />
                    </Field>
                    <div className="flex items-center justify-between pt-6">
                      <span className="text-sm font-medium">PFS</span>
                      <Toggle checked={tForm.ipsecPfs} onChange={(v) => setT("ipsecPfs", v)} />
                    </div>
                  </div>
                </div>
              )}
            </div>

            <div className="flex flex-col gap-4">
              <button type="button" onClick={() => setT("showAdvanced", !tForm.showAdvanced)}
                className="flex items-center gap-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground hover:text-foreground transition-colors">
                {tForm.showAdvanced ? <ChevronDownIcon className="size-3.5" /> : <ChevronRightIcon className="size-3.5" />}
                Дополнительно
                <div className="flex-1 h-px bg-border" />
              </button>
              {tForm.showAdvanced && (
                <div className="flex flex-col gap-4">
                  <div className="grid grid-cols-3 gap-3">
                    <Field label="MTU" hint="По умолч. 1476">
                      <Input type="number" className="font-mono" value={tForm.mtu} onChange={(e) => setT("mtu", Number(e.target.value))} />
                    </Field>
                    <Field label="Keepalive, с" hint="0 = откл.">
                      <Input type="number" className="font-mono" value={tForm.keepaliveInterval} onChange={(e) => setT("keepaliveInterval", Number(e.target.value))} />
                    </Field>
                    <Field label="Попытки">
                      <Input type="number" className="font-mono" value={tForm.keepaliveRetries} onChange={(e) => setT("keepaliveRetries", Number(e.target.value))} />
                    </Field>
                  </div>
                  <Field label="DSCP">
                    <select value={tForm.dscp} onChange={(e) => setT("dscp", e.target.value)}
                      className="h-8 w-full rounded-lg border border-input bg-transparent px-2.5 text-sm outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50">
                      <option value="inherit">inherit</option>
                      {Array.from({ length: 64 }, (_, i) => <option key={i} value={String(i)}>{i}</option>)}
                    </select>
                  </Field>
                  {[
                    { key: "clampTcpMss" as const, label: "Clamp TCP MSS", desc: "Ограничить MSS до MTU туннеля" },
                    { key: "allowFastPath" as const, label: "Allow Fast Path", desc: "Аппаратное ускорение трафика" },
                  ].map(({ key, label, desc }) => (
                    <div key={key} className="flex items-center justify-between">
                      <div>
                        <p className="text-sm font-medium">{label}</p>
                        <p className="text-xs text-muted-foreground">{desc}</p>
                      </div>
                      <Toggle checked={tForm[key] as boolean} onChange={(v) => setT(key, v)} />
                    </div>
                  ))}
                </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={() => setTunnelOpen(false)}>Создать туннель</Button>
          </SheetFooter>
        </SheetContent>
      </Sheet>

      {/* ══ Sheet: Add Pool ════════════════════════════════════════════════════ */}
      <Sheet open={poolOpen} onOpenChange={setPoolOpen}>
        <SheetContent side="right" className="w-full sm:max-w-md flex flex-col gap-0 p-0">
          <SheetHeader className="px-6 pt-6 pb-4 border-b shrink-0">
            <SheetTitle>Новый IP-пул</SheetTitle>
            <SheetDescription>Пул адресов для назначения внутренних IP GRE-туннелям</SheetDescription>
          </SheetHeader>
          <div className="flex-1 overflow-y-auto px-6 py-5 flex flex-col gap-5">
            <div className="flex flex-col gap-4">
              <SectionTitle>Параметры пула</SectionTitle>
              <Field label="Имя пула" required hint="Например pool-gre-office или pool-gre-dc2">
                <Input className="font-mono" placeholder="pool-gre-core" value={pForm.name}
                  onChange={(e) => setPForm((f) => ({ ...f, name: e.target.value }))} />
              </Field>
              <Field label="Диапазон CIDR" required hint="Блок, из которого будут нарезаться /30 на каждый туннель">
                <Input className="font-mono" placeholder="10.200.0.0/24" value={pForm.cidr}
                  onChange={(e) => setPForm((f) => ({ ...f, cidr: e.target.value }))} />
              </Field>
              <Field label="Назначение / Комментарий">
                <Input placeholder="Ядровые межузловые туннели" value={pForm.comment}
                  onChange={(e) => setPForm((f) => ({ ...f, comment: e.target.value }))} />
              </Field>
              {pForm.cidr && /\/\d+$/.test(pForm.cidr) && (() => {
                const prefix = parseInt(pForm.cidr.split("/")[1] ?? "0")
                const blocks = prefix <= 30 ? Math.pow(2, 30 - prefix) : 0
                return blocks > 0 ? (
                  <div className="rounded-lg border border-border bg-muted/30 px-4 py-3 text-sm">
                    <p className="text-muted-foreground">
                      Доступно <span className="font-semibold text-foreground font-mono">{blocks}</span> блоков /30
                      {" "}= до <span className="font-semibold text-foreground font-mono">{blocks}</span> туннелей
                    </p>
                  </div>
                ) : null
              })()}
            </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={() => setPoolOpen(false)}>Создать пул</Button>
          </SheetFooter>
        </SheetContent>
      </Sheet>
    </div>
  )
}
