export type ServerStatus = "online" | "offline" | "degraded"
export type ServerType = "jump-host" | "exit-node" | "home-router"

export interface WanUplink {
  id: string
  name: string      // "WAN1-RT"
  isp: string       // "Rostelecom"
  iface: string     // "ether1"
  ip: string        // external IP
  maxDl: number     // Mbps
  maxUl: number     // Mbps
}

// ─── WireGuard ───────────────────────────────────────────────────────────────

export interface WireGuardPeer {
  id?: string
  rosId?: string
  publicKey: string
  allowedIps: string[]
  endpoint?: string        // "1.2.3.4:13231"
  latestHandshake?: string // "2 минуты назад"
  transferRx?: number      // bytes
  transferTx?: number      // bytes
  persistentKeepalive?: number
  persistent?: boolean
  comment?: string
  disabled?: boolean
  name?: string
  clientAddress?: string
  clientDns?: string
  clientEndpoint?: string
}

export interface WireGuardInterface {
  id: string
  rosId?: string
  name: string             // e.g. "wg-msk-spb"
  listenPort: number       // default 13231
  mtu: number              // 1420 default in ROS 7.x
  publicKey?: string
  privateKey?: string
  address?: string
  peers: WireGuardPeer[]
  comment: string
  enabled: boolean
  status: "up" | "down"
}

export interface Server {
  id: string
  name: string
  host: string      // management IP / API address
  model: string
  os: string
  site: string
  country: string   // ISO 3166-1 alpha-2, e.g. "RU", "DE"
  asn: string
  type: ServerType
  enabled: boolean
  status: ServerStatus
  latency: number | null
  sessions: number
  comment?: string
  // RouterOS 7.x extras
  ipv6Address?: string          // global or link-local
  wireGuardIfaces?: WireGuardInterface[]
  vrfNames?: string[]           // VRF instances on this router
  rpkiEnabled?: boolean
  // home-router specific
  wanUplinks?: WanUplink[]
  lanSubnet?: string   // e.g. "192.168.10.0/24"
  // snapshot / poll data (как GET /api/servers — последний poll MikroTik)
  uptime?: string
  cpuLoad?: number
  /** байты, поля RouterOS resource */
  freeMemory?: number
  totalMemory?: number
  polledAt?: string
}

export interface FlowspecRule {
  id: string
  dstPrefix?: string
  srcPrefix?: string
  ipProto?: string
  dstPort?: string
  action: "rate-limit" | "discard" | "redirect"
  rate?: number       // Mbps, for rate-limit
  comment?: string
}

export interface Filter {
  id: string
  name: string
  domains: number
  ips: number
  asns: number
  servers: string[]
  enabled: boolean
  updated: string
  communities: string[]
  gateway: string
  // RouterOS 7.x extras
  largeCommunities?: string[]     // RFC 8092 format "AS:VALUE1:VALUE2"
  rpkiValid?: boolean             // filter only RPKI-valid routes
  flowspecRules?: FlowspecRule[]
}

export interface Domain {
  id: string
  domain: string
  resolvedIp: string
  asn: string
  purpose: string
  filter: string
  updated: string
  enabled: boolean
}

export interface IpRange {
  id: string
  cidr: string
  asn: string
  country: string
  purpose: string
  filter: string
  updated: string
  enabled: boolean
}

export interface Asn {
  id: string
  asn: string
  org: string
  country: string
  prefixes: number
  filter: string
  updated: string
  enabled: boolean
}

export type FirewallAction =
  | "accept" | "drop" | "reject" | "mark-routing" | "mark-conn"
  | "masquerade" | "src-nat" | "dst-nat"
  | "fasttrack-connection" | "nfqueue" | "passthrough" | "return"
  | "add-src-to-address-list" | "add-dst-to-address-list"

export type FirewallTable = "filter" | "nat" | "mangle" | "raw"

export interface FirewallRule {
  id: string
  chain: string
  action: FirewallAction | string
  proto: string
  src: string
  dst: string
  port: string
  iface: string
  comment: string
  enabled: boolean
  hits: number
  family?: "ip" | "ip6" | "any"
  table?: FirewallTable
  serverId?: string
  serverName?: string
  rosId?: string
  tlsHost?: string
  connRateLimit?: string
  layer7Proto?: string
  nfqueueId?: number
  log?: boolean
  logPrefix?: string
}

export interface FirewallAddressListEntry {
  id: string
  list: string
  address: string
  comment: string
  disabled: boolean
  timeout?: string
  family?: "ip" | "ip6"
  serverId?: string
  serverName?: string
  rosId?: string
}

export interface Backup {
  id: string
  server: string
  filename: string
  size: string
  created: string
  kind: "auto" | "manual"
  notes: string
}

// ─── VXLAN ───────────────────────────────────────────────────────────────────

export interface VxlanTunnel {
  id: string
  name: string           // "vxlan-overlay-1"
  vni: number            // 0–16777215
  port: number           // source port (default 0 = auto)
  dstPort: number        // destination port (default 8472)
  serverId: string
  vtepIp: string         // VTEP address on the server
  remoteVteps: string[]  // remote VTEP IPs (unicast-flood)
  l2mtu: number
  arpProxy: boolean
  macLearning: boolean
  comment: string
  enabled: boolean
  status: "up" | "down"
}

// ─── VRF ─────────────────────────────────────────────────────────────────────

export interface VrfInstance {
  id: string
  name: string           // VRF name
  serverId: string
  interfaces: string[]   // list of interfaces in this VRF
  routingTable: string   // associated routing table
  comment: string
}

// ─── Container (RouterOS 7.4+) ───────────────────────────────────────────────

export interface RouterContainer {
  id: string
  name: string
  serverId: string
  image: string          // e.g. "nginx:alpine"
  tag: string
  status: "running" | "stopped" | "error"
  envs: { key: string; value: string }[]
  mounts: { dst: string; src?: string }[]
  interfaces: string[]   // veth interface names
  cmd?: string
  startOnBoot: boolean
  comment: string
  uptime?: string
  cpu?: number           // CPU % 0-100
  memMb?: number         // MB
}

// ─── Certificate ─────────────────────────────────────────────────────────────

export type CertUsage = "server" | "client" | "ca" | "crl-sign"
export type CertStatus = "valid" | "expired" | "revoked"

export interface RouterCertificate {
  id: string
  name: string
  serverId: string
  commonName: string
  sans: string[]
  issuedBy: string
  validFrom: string
  validUntil: string
  daysLeft: number
  keySize: number
  usage: CertUsage[]
  trusted: boolean
  status: CertStatus
}

export interface PingProbe {
  id: string
  srcServerId: string    // which server sends the ping
  srcInterface?: string  // optional interface name on source router
  name: string
  target: string
  filter: string
  rtt: number | null
  loss: number
  status: "up" | "warn" | "down"
  series: number[]
  enabled: boolean
  /** Показывать в блоке «Активные пробы» на дашборде (звезда в мониторинге) */
  showOnDashboard?: boolean
}

export interface SystemEvent {
  id: string
  sev: "destructive" | "warning" | "info"
  title: string
  message: string
  when: string
}

function spark(n: number, base: number, range: number): number[] {
  let s = base * 1000 + range
  return Array.from({ length: n }, () => {
    s = (s * 9301 + 49297) % 233280
    const r = s / 233280
    return Math.max(1, Math.round(base + (r - 0.5) * range * 2))
  })
}

export const servers: Server[] = [
  {
    id: "srv1", name: "mt-msk-core-01", host: "10.0.0.1", model: "CCR2004-1G-12S+2XS", os: "7.20.1",
    site: "MSK", country: "RU", asn: "AS65001", type: "jump-host", enabled: true, status: "online", latency: 12, sessions: 4,
    ipv6Address: "2a01:4f8:1c1c:a1b2::1",
    rpkiEnabled: true,
    vrfNames: ["mgmt", "bypass"],
    wireGuardIfaces: [
      {
        id: "wg1", name: "wg-msk-spb", listenPort: 13231, mtu: 1420, comment: "MSK → SPB overlay", enabled: true, status: "up",
        peers: [
          { publicKey: "SPBPublicKeyBase64AAAAAAAAAAAAAAAAAAAAAA=", allowedIps: ["10.210.0.2/32","192.168.20.0/24"], endpoint: "10.0.1.1:13231", latestHandshake: "2 мин назад", transferRx: 182_400_000, transferTx: 64_800_000, persistent: true },
        ],
      },
      {
        id: "wg2", name: "wg-msk-fra", listenPort: 13232, mtu: 1420, comment: "MSK → FRA overlay", enabled: true, status: "up",
        peers: [
          { publicKey: "FRAPublicKeyBase64AAAAAAAAAAAAAAAAAAAAAA=", allowedIps: ["10.210.0.6/32"], endpoint: "10.0.2.1:13231", latestHandshake: "1 мин назад", transferRx: 421_000_000, transferTx: 210_000_000, persistent: true },
        ],
      },
    ],
  },
  {
    id: "srv2", name: "mt-spb-edge-01", host: "10.0.1.1", model: "CCR2116-12G-4S+", os: "7.20.1",
    site: "SPB", country: "RU", asn: "AS65002", type: "exit-node", enabled: true, status: "online", latency: 28, sessions: 6,
    ipv6Address: "2a01:4f8:1c2c:b2c3::1",
    rpkiEnabled: true,
    wireGuardIfaces: [
      {
        id: "wg3", name: "wg-spb-msk", listenPort: 13231, mtu: 1420, comment: "SPB → MSK overlay", enabled: true, status: "up",
        peers: [
          { publicKey: "MSKPublicKeyBase64AAAAAAAAAAAAAAAAAAAAAA=", allowedIps: ["10.210.0.1/32"], endpoint: "10.0.0.1:13231", latestHandshake: "2 мин назад", transferRx: 64_800_000, transferTx: 182_400_000, persistent: true },
        ],
      },
    ],
  },
  {
    id: "srv3", name: "mt-fra-edge-01", host: "10.0.2.1", model: "CCR2004-16G-2S+", os: "7.20.1",
    site: "FRA", country: "DE", asn: "AS65003", type: "exit-node", enabled: true, status: "online", latency: 41, sessions: 3,
    ipv6Address: "2a01:4f8:1c3c:c3d4::1",
    rpkiEnabled: true,
    wireGuardIfaces: [
      {
        id: "wg4", name: "wg-fra-msk", listenPort: 13231, mtu: 1420, comment: "FRA → MSK overlay", enabled: true, status: "up",
        peers: [
          { publicKey: "MSKPublicKeyBase64AAAAAAAAAAAAAAAAAAAAAA=", allowedIps: ["10.210.0.1/32"], endpoint: "10.0.0.1:13232", latestHandshake: "1 мин назад", transferRx: 210_000_000, transferTx: 421_000_000, persistent: true },
        ],
      },
    ],
  },
  {
    id: "srv4", name: "mt-ams-edge-01", host: "10.0.3.1", model: "RB5009UG+S+IN", os: "7.19.3",
    site: "AMS", country: "NL", asn: "AS65004", type: "exit-node", enabled: true, status: "degraded", latency: 88, sessions: 2,
  },
  {
    id: "srv5", name: "mt-sgp-edge-01", host: "10.0.4.1", model: "CCR2004-1G-12S+2XS", os: "7.14.2",
    site: "SGP", country: "SG", asn: "AS65005", type: "exit-node", enabled: false, status: "offline", latency: null, sessions: 0,
  },
  {
    id: "srv6", name: "mt-ams-test-01", host: "10.0.3.2", model: "hEX S", os: "7.20.1",
    site: "AMS", country: "NL", asn: "AS65006", type: "jump-host", enabled: true, status: "online", latency: 92, sessions: 1,
  },
  {
    id: "srv7", name: "mt-msk-lab-01", host: "10.0.0.7", model: "RB5009UG+S+IN", os: "7.20.1",
    site: "MSK", country: "RU", asn: "AS65007", type: "jump-host", enabled: true, status: "online", latency: 14, sessions: 2,
    vrfNames: ["lab"],
  },
  {
    id: "home1", name: "home-msk-01", host: "192.168.10.1", model: "hEX S (RB760iGS)", os: "7.20.1",
    site: "MSK", country: "RU", asn: "", type: "home-router", enabled: true, status: "online", latency: 3, sessions: 0,
    comment: "MSK офис — основной роутер",
    lanSubnet: "192.168.10.0/24",
    wanUplinks: [
      { id: "w1a", name: "WAN1-RT", isp: "Rostelecom", iface: "ether1", ip: "94.25.168.1",  maxDl: 500, maxUl: 500 },
      { id: "w1b", name: "WAN2-BL", isp: "Beeline",    iface: "ether2", ip: "85.174.12.1",  maxDl: 100, maxUl: 100 },
    ],
  },
  {
    id: "home2", name: "home-spb-01", host: "192.168.20.1", model: "RB5009UG+S+IN", os: "7.20.1",
    site: "SPB", country: "RU", asn: "", type: "home-router", enabled: true, status: "online", latency: 5, sessions: 0,
    comment: "SPB офис — основной роутер",
    lanSubnet: "192.168.20.0/24",
    wanUplinks: [
      { id: "w2a", name: "WAN1-MTS", isp: "МТС",        iface: "ether1", ip: "178.214.4.1",  maxDl: 300, maxUl: 300 },
      { id: "w2b", name: "WAN2-ERT", isp: "ЭР-Телеком", iface: "ether2", ip: "95.31.14.1",   maxDl: 200, maxUl: 150 },
    ],
  },
]

export const filters: Filter[] = [
  {
    id: "f1", name: "youtube-bypass", domains: 1842, ips: 4218, asns: 12,
    servers: ["srv1","srv2","srv3","srv4"], enabled: true, updated: "12 мин назад",
    communities: ["65001:100","65001:200"], gateway: "10.0.0.1",
    largeCommunities: ["65001:100:1","65001:100:2"],
    rpkiValid: true,
  },
  {
    id: "f2", name: "streaming-eu", domains: 612, ips: 2104, asns: 8,
    servers: ["srv2","srv3","srv4"], enabled: true, updated: "2 ч назад",
    communities: ["65001:200"], gateway: "10.0.1.1",
    largeCommunities: ["65001:200:1"],
    rpkiValid: true,
  },
  {
    id: "f3", name: "cdn-bypass", domains: 4218, ips: 18211, asns: 22,
    servers: ["srv1","srv2","srv3","srv4","srv6"], enabled: true, updated: "1 ч назад",
    communities: ["65001:300","65002:100"], gateway: "10.0.0.1",
    flowspecRules: [
      { id: "fs1", dstPrefix: "104.16.0.0/12", ipProto: "tcp", dstPort: "443", action: "rate-limit", rate: 100, comment: "CF rate-limit" },
    ],
  },
  { id: "f4", name: "social-block-school", domains: 84,   ips: 412,  asns: 4,  servers: ["srv1","srv7"],                          enabled: false, updated: "3 дн назад",   communities: ["65007:999"],             gateway: "" },
  { id: "f5", name: "office-direct",       domains: 142,  ips: 884,  asns: 6,  servers: ["srv1","srv2","srv3","srv4","srv6","srv7"], enabled: true, updated: "4 ч назад",   communities: ["65001:400"],             gateway: "10.0.0.1" },
  { id: "f6", name: "gaming-low-latency",  domains: 88,   ips: 1212, asns: 14, servers: ["srv1","srv2","srv3","srv7"],             enabled: true,  updated: "24 мин назад", communities: ["65001:500","65002:200"], gateway: "10.0.2.1" },
]

export const domains: Domain[] = [
  { id: "d1",  domain: "youtube.com",      purpose: "streaming", filter: "youtube-bypass",      resolvedIp: "142.250.74.110",  asn: "AS15169", updated: "12 мин",  enabled: true  },
  { id: "d2",  domain: "googlevideo.com",  purpose: "streaming", filter: "youtube-bypass",      resolvedIp: "142.250.74.142",  asn: "AS15169", updated: "12 мин",  enabled: true  },
  { id: "d3",  domain: "ytimg.com",        purpose: "streaming", filter: "youtube-bypass",      resolvedIp: "172.217.16.46",   asn: "AS15169", updated: "12 мин",  enabled: true  },
  { id: "d4",  domain: "netflix.com",      purpose: "streaming", filter: "streaming-eu",        resolvedIp: "54.246.79.9",     asn: "AS2906",  updated: "2 ч",     enabled: true  },
  { id: "d5",  domain: "nflxvideo.net",    purpose: "streaming", filter: "streaming-eu",        resolvedIp: "45.57.32.18",     asn: "AS2906",  updated: "2 ч",     enabled: true  },
  { id: "d6",  domain: "cloudflare.com",   purpose: "cdn",       filter: "cdn-bypass",          resolvedIp: "104.16.132.229",  asn: "AS13335", updated: "1 ч",     enabled: true  },
  { id: "d7",  domain: "akamaized.net",    purpose: "cdn",       filter: "cdn-bypass",          resolvedIp: "23.46.18.94",     asn: "AS20940", updated: "1 ч",     enabled: true  },
  { id: "d8",  domain: "fastly.net",       purpose: "cdn",       filter: "cdn-bypass",          resolvedIp: "151.101.1.95",    asn: "AS54113", updated: "1 ч",     enabled: true  },
  { id: "d9",  domain: "twitch.tv",        purpose: "streaming", filter: "streaming-eu",        resolvedIp: "52.223.241.72",   asn: "AS16509", updated: "2 ч",     enabled: false },
  { id: "d10", domain: "discord.com",      purpose: "voip",      filter: "gaming-low-latency",  resolvedIp: "162.159.135.232", asn: "AS13335", updated: "24 мин",  enabled: true  },
  { id: "d11", domain: "steam.com",        purpose: "gaming",    filter: "gaming-low-latency",  resolvedIp: "23.45.139.40",    asn: "AS20940", updated: "24 мин",  enabled: true  },
  { id: "d12", domain: "epicgames.com",    purpose: "gaming",    filter: "gaming-low-latency",  resolvedIp: "34.205.247.51",   asn: "AS16509", updated: "24 мин",  enabled: true  },
]

export const ipRanges: IpRange[] = [
  { id: "i1", cidr: "142.250.0.0/15",   purpose: "streaming", filter: "youtube-bypass",     asn: "AS15169", country: "US", updated: "12 мин", enabled: true  },
  { id: "i2", cidr: "172.217.0.0/16",   purpose: "streaming", filter: "youtube-bypass",     asn: "AS15169", country: "US", updated: "12 мин", enabled: true  },
  { id: "i3", cidr: "104.16.0.0/12",    purpose: "cdn",       filter: "cdn-bypass",         asn: "AS13335", country: "US", updated: "1 ч",    enabled: true  },
  { id: "i4", cidr: "23.32.0.0/11",     purpose: "cdn",       filter: "cdn-bypass",         asn: "AS20940", country: "US", updated: "1 ч",    enabled: true  },
  { id: "i5", cidr: "151.101.0.0/16",   purpose: "cdn",       filter: "cdn-bypass",         asn: "AS54113", country: "US", updated: "1 ч",    enabled: true  },
  { id: "i6", cidr: "54.246.0.0/16",    purpose: "streaming", filter: "streaming-eu",       asn: "AS2906",  country: "IE", updated: "2 ч",    enabled: true  },
  { id: "i7", cidr: "45.57.0.0/16",     purpose: "streaming", filter: "streaming-eu",       asn: "AS2906",  country: "NL", updated: "2 ч",    enabled: true  },
  { id: "i8", cidr: "162.159.128.0/19", purpose: "voip",      filter: "gaming-low-latency", asn: "AS13335", country: "US", updated: "24 мин", enabled: true  },
  { id: "i9", cidr: "52.223.240.0/20",  purpose: "streaming", filter: "streaming-eu",       asn: "AS16509", country: "IE", updated: "2 ч",    enabled: false },
]

export const asns: Asn[] = [
  { id: "a1", asn: "AS15169", org: "GOOGLE",           country: "US", prefixes: 842,  filter: "youtube-bypass",     updated: "12 мин", enabled: true  },
  { id: "a2", asn: "AS13335", org: "CLOUDFLARENET",    country: "US", prefixes: 1284, filter: "cdn-bypass",         updated: "1 ч",    enabled: true  },
  { id: "a3", asn: "AS16509", org: "AMAZON-02",        country: "US", prefixes: 4128, filter: "streaming-eu",       updated: "2 ч",    enabled: true  },
  { id: "a4", asn: "AS20940", org: "AKAMAI-ASN1",      country: "US", prefixes: 614,  filter: "cdn-bypass",         updated: "1 ч",    enabled: true  },
  { id: "a5", asn: "AS54113", org: "FASTLY",           country: "US", prefixes: 122,  filter: "cdn-bypass",         updated: "1 ч",    enabled: true  },
  { id: "a6", asn: "AS2906",  org: "AS-SSI (Netflix)", country: "US", prefixes: 88,   filter: "streaming-eu",       updated: "2 ч",    enabled: true  },
  { id: "a7", asn: "AS32934", org: "FACEBOOK",         country: "US", prefixes: 412,  filter: "social-block-school",updated: "3 дн",   enabled: false },
  { id: "a8", asn: "AS8075",  org: "MICROSOFT-CORP",   country: "US", prefixes: 882,  filter: "office-direct",      updated: "4 ч",    enabled: true  },
]

export const firewallRules: FirewallRule[] = [
  { id: "fw1", table: "filter", family: "ip", serverId: "srv1", serverName: "mt-msk-core-01", rosId: "*1", chain: "forward", action: "accept",       proto: "tcp", src: "youtube-bypass",  dst: "0.0.0.0/0",           port: "443",        iface: "wan-bgp",    comment: "YouTube bypass traffic",      enabled: true,  hits: 188421    },
  { id: "fw2", table: "mangle", family: "ip", serverId: "srv1", serverName: "mt-msk-core-01", rosId: "*1", chain: "forward", action: "mark-routing", proto: "tcp", src: "10.10.0.0/24",    dst: "cdn-bypass",           port: "—",          iface: "lan",        comment: "CDN routing mark",            enabled: true,  hits: 4128821   },
  { id: "fw3", table: "nat",    family: "ip", serverId: "srv1", serverName: "mt-msk-core-01", rosId: "*1", chain: "srcnat",  action: "masquerade",   proto: "all", src: "10.10.0.0/16",    dst: "0.0.0.0/0",           port: "—",          iface: "wan-msk",    comment: "Main NAT rule",               enabled: true,  hits: 12889241  },
  { id: "fw4", table: "filter", family: "ip", serverId: "srv1", serverName: "mt-msk-core-01", rosId: "*2", chain: "forward", action: "drop",         proto: "tcp", src: "0.0.0.0/0",       dst: "social-block-school",  port: "—",          iface: "lan-school", comment: "School social block",         enabled: true,  hits: 4218      },
  { id: "fw5", table: "filter", family: "ip", serverId: "srv1", serverName: "mt-msk-core-01", rosId: "*3", chain: "input",   action: "accept",       proto: "tcp", src: "10.10.0.0/16",    dst: "—",                   port: "22,443,8291",iface: "—",          comment: "Management access",           enabled: true,  hits: 18412     },
  { id: "fw6", table: "filter", family: "ip", serverId: "srv1", serverName: "mt-msk-core-01", rosId: "*4", chain: "input",   action: "drop",         proto: "tcp", src: "0.0.0.0/0",       dst: "—",                   port: "22",         iface: "wan-msk",    comment: "Block SSH from WAN",          enabled: true,  hits: 882412    },
  { id: "fw7", table: "filter", family: "ip6", serverId: "srv1", serverName: "mt-msk-core-01", rosId: "*1", chain: "input",   action: "accept",      proto: "icmpv6", src: "fe80::/10", dst: "—", port: "—", iface: "—", comment: "IPv6 link-local ICMPv6", enabled: true, hits: 1204 },
  { id: "fw8", table: "filter", family: "ip6", serverId: "srv1", serverName: "mt-msk-core-01", rosId: "*2", chain: "forward", action: "accept",      proto: "tcp", src: "2a01:4f8::/32", dst: "::/0", port: "443", iface: "wan-bgp", comment: "IPv6 HTTPS forward", enabled: true, hits: 88421 },
]

export const backups: Backup[] = [
  { id: "b1", server: "mt-msk-core-01", filename: "mt-msk-core-01_2026-04-26_03-00.rsc", size: "124 КБ", created: "Сегодня, 03:00", kind: "auto",   notes: "снапшот перед обновлением" },
  { id: "b2", server: "mt-msk-core-01", filename: "mt-msk-core-01_2026-04-25_03-00.rsc", size: "124 КБ", created: "Вчера, 03:00",   kind: "auto",   notes: "" },
  { id: "b3", server: "mt-spb-edge-01", filename: "mt-spb-edge-01_2026-04-26_03-00.rsc", size: "88 КБ",  created: "Сегодня, 03:00", kind: "auto",   notes: "" },
  { id: "b4", server: "mt-fra-edge-01", filename: "mt-fra-edge-01_2026-04-26_manual.rsc",size: "92 КБ",  created: "Сегодня, 14:18", kind: "manual", notes: "перед изменением BGP" },
  { id: "b5", server: "mt-ams-edge-01", filename: "mt-ams-edge-01_2026-04-25_03-00.rsc", size: "64 КБ",  created: "Вчера, 03:00",   kind: "auto",   notes: "" },
]

export const pingProbes: PingProbe[] = [
  // srv1 — mt-msk-core-01 (JH, MSK) → основной мониторинг
  { id: "p1",  srcServerId: "srv1", name: "youtube.com",    target: "142.250.74.110",  filter: "youtube-bypass",     rtt: 18,  loss: 0,   status: "up",   series: spark(40, 18, 4),  enabled: true  },
  { id: "p2",  srcServerId: "srv1", name: "cloudflare.com", target: "104.16.132.229",  filter: "cdn-bypass",         rtt: 4,   loss: 0,   status: "up",   series: spark(40, 4, 1),   enabled: true  },
  { id: "p3",  srcServerId: "srv1", name: "netflix-eu",     target: "54.246.79.9",     filter: "streaming-eu",       rtt: 28,  loss: 0,   status: "up",   series: spark(40, 28, 5),  enabled: true  },
  { id: "p4",  srcServerId: "srv1", name: "fastly-edge",    target: "151.101.1.95",    filter: "cdn-bypass",         rtt: 8,   loss: 0,   status: "up",   series: spark(40, 8, 2),   enabled: true  },
  // srv7 — mt-msk-lab-01 (JH, MSK) → лаборатория
  { id: "p5",  srcServerId: "srv7", name: "discord-voip",   target: "162.159.135.232", filter: "gaming-low-latency", rtt: 12,  loss: 0,   status: "up",   series: spark(40, 12, 2),  enabled: true  },
  { id: "p6",  srcServerId: "srv7", name: "steam-cdn",      target: "23.45.139.40",    filter: "gaming-low-latency", rtt: 38,  loss: 1.2, status: "warn", series: spark(40, 38, 12), enabled: true  },
  { id: "p7",  srcServerId: "srv7", name: "akamai-edge",    target: "23.46.18.94",     filter: "cdn-bypass",         rtt: 22,  loss: 0,   status: "up",   series: spark(40, 22, 4),  enabled: true  },
  // srv2 — mt-spb-edge-01 (EN, SPB) → исходящий трафик SPB
  { id: "p8",  srcServerId: "srv2", name: "youtube.com",    target: "142.250.74.110",  filter: "youtube-bypass",     rtt: 22,  loss: 0,   status: "up",   series: spark(40, 22, 5),  enabled: true  },
  { id: "p9",  srcServerId: "srv2", name: "office-365",     target: "104.47.0.22",     filter: "office-direct",      rtt: 31,  loss: 0,   status: "up",   series: spark(40, 31, 6),  enabled: false },
  // srv3 — mt-fra-edge-01 (EN, FRA) → исходящий трафик Frankfurt
  { id: "p10", srcServerId: "srv3", name: "youtube.com",    target: "142.250.74.110",  filter: "youtube-bypass",     rtt: 12,  loss: 0,   status: "up",   series: spark(40, 12, 3),  enabled: true  },
  { id: "p11", srcServerId: "srv3", name: "netflix-eu",     target: "54.246.79.9",     filter: "streaming-eu",       rtt: 9,   loss: 0,   status: "up",   series: spark(40, 9, 2),   enabled: true  },
  // srv4 — mt-ams-edge-01 (EN, AMS, degraded) → деградировавший узел
  { id: "p12", srcServerId: "srv4", name: "cloudflare.com", target: "104.16.132.229",  filter: "cdn-bypass",         rtt: 88,  loss: 3.4, status: "warn", series: spark(40, 88, 22), enabled: true  },
  { id: "p13", srcServerId: "srv4", name: "sgp-probe",      target: "139.180.22.4",    filter: "—",                  rtt: null,loss: 100, status: "down", series: Array(40).fill(0), enabled: true  },
]

export const systemEvents: SystemEvent[] = [
  { id: "e1", sev: "destructive", title: "BGP-сессия упала",               message: "mt-sgp-edge-01 · пир 139.180.22.4 · простой 2ч",       when: "2ч" },
  { id: "e2", sev: "destructive", title: "Ошибка синхронизации фильтра",   message: "cdn-bypass → mt-ams-edge-01 · таймаут",                 when: "14м" },
  { id: "e3", sev: "warning",     title: "Высокая задержка на AMS",        message: "среднее 88мс · порог 60мс",                            when: "8м"  },
  { id: "e4", sev: "warning",     title: "Бэкап просрочен",                message: "mt-msk-lab-01 · последний 5д назад",                    when: "1ч"  },
  { id: "e5", sev: "info",        title: "Обновление BGP завершено",       message: "+412 префиксов · −188 отозвано",                       when: "12м" },
  { id: "e6", sev: "info",        title: "Фильтр youtube-bypass обновлён", message: "+88 доменов · ↑ 24 сервера",                           when: "12м" },
]

export const dashLatency = {
  msk: spark(60, 12, 4),
  spb: spark(60, 28, 6),
  fra: spark(60, 41, 9),
  ams: spark(60, 88, 18),
}

export const traffic = {
  rx: Array.from({ length: 60 }, (_, i) => Math.round(280 + Math.sin(i / 6) * 60 + ((i * 7919) % 31))),
  tx: Array.from({ length: 60 }, (_, i) => Math.round(220 + Math.sin(i / 5) * 50 + ((i * 6271) % 21))),
}

// ─── GRE ────────────────────────────────────────────────────────────────────

export type GreStatus = "up" | "down" | "degraded"
export type IpsecEncAlg = "aes-128" | "aes-192" | "aes-256"
export type IpsecAuthAlg = "sha1" | "sha256" | "sha512"
export type IpsecDhGroup = "modp1024" | "modp2048" | "modp4096" | "ecp256" | "ecp384" | "ecp521"
export type IkeVersion = "ikev1" | "ikev2"
export type DscpMode = "inherit" | number

export interface GreIpsec {
  secret: string          // ipsec-secret → auto-creates peer+policy+proposal
  encAlg: IpsecEncAlg    // proposal enc-algorithms
  authAlg: IpsecAuthAlg  // proposal auth-algorithms
  dhGroup: IpsecDhGroup  // proposal pfs-group / peer dh-group
  ikeVersion: IkeVersion // peer exchange-mode
  lifetime: string       // proposal lifetime (e.g. "1d 00:00:00")
  pfs: boolean           // perfect forward secrecy
}

export interface GreTunnel {
  id: string
  name: string            // interface name, e.g. gre-msk-spb
  serverId: string        // which MikroTik runs this tunnel
  localAddress: string    // local GRE endpoint ("0.0.0.0" = auto)
  remoteAddress: string   // remote GRE endpoint (required)
  localInnerIp: string    // /ip address on this side, e.g. 10.200.0.1/30
  remoteInnerIp: string   // /ip address on remote side, e.g. 10.200.0.2/30
  poolId: string          // which IP pool the inner IPs come from
  ipsec: GreIpsec | null  // null = no IPsec (plain GRE)
  mtu: number             // default 1476
  keepaliveInterval: number  // seconds, 0 = disabled
  keepaliveRetries: number
  dscp: DscpMode          // "inherit" or 0-63
  clampTcpMss: boolean
  allowFastPath: boolean
  comment: string
  enabled: boolean
  status: GreStatus
}

export interface GrePool {
  id: string
  name: string
  cidr: string
  allocated: number
  total: number
  comment: string
}

const defaultIpsec = (secret: string, ikeVersion: IkeVersion = "ikev2"): GreIpsec => ({
  secret,
  encAlg: "aes-256",
  authAlg: "sha256",
  dhGroup: "modp2048",
  ikeVersion,
  lifetime: "1d 00:00:00",
  pfs: true,
})

export const grePools: GrePool[] = [
  { id: "gp1", name: "pool-gre-core", cidr: "10.200.0.0/24", allocated: 16, total: 64, comment: "Ядровые межузловые туннели" },
  { id: "gp2", name: "pool-gre-mgmt", cidr: "10.201.0.0/24", allocated:  8, total: 64, comment: "Управляющие туннели (lab, test)" },
]

export const greTunnels: GreTunnel[] = [
  {
    id: "gre1", name: "gre-msk-spb", serverId: "srv1",
    localAddress: "10.0.0.1", remoteAddress: "10.0.1.1",
    localInnerIp: "10.200.0.1/30", remoteInnerIp: "10.200.0.2/30", poolId: "gp1",
    ipsec: defaultIpsec("xK9#mQ2$vLp8nR4"),
    mtu: 1476, keepaliveInterval: 10, keepaliveRetries: 10,
    dscp: "inherit", clampTcpMss: true, allowFastPath: true,
    comment: "MSK → SPB core interconnect", enabled: true, status: "up",
  },
  {
    id: "gre2", name: "gre-msk-fra", serverId: "srv1",
    localAddress: "10.0.0.1", remoteAddress: "10.0.2.1",
    localInnerIp: "10.200.0.5/30", remoteInnerIp: "10.200.0.6/30", poolId: "gp1",
    ipsec: defaultIpsec("pW3@jT7!hD5kYe1"),
    mtu: 1476, keepaliveInterval: 10, keepaliveRetries: 10,
    dscp: "inherit", clampTcpMss: true, allowFastPath: true,
    comment: "MSK → FRA core interconnect", enabled: true, status: "up",
  },
  {
    id: "gre3", name: "gre-msk-ams", serverId: "srv1",
    localAddress: "10.0.0.1", remoteAddress: "10.0.3.1",
    localInnerIp: "10.200.0.9/30", remoteInnerIp: "10.200.0.10/30", poolId: "gp1",
    ipsec: defaultIpsec("rN6%bF2*cM8sZa0"),
    mtu: 1476, keepaliveInterval: 10, keepaliveRetries: 10,
    dscp: "inherit", clampTcpMss: true, allowFastPath: false,
    comment: "MSK → AMS core interconnect", enabled: true, status: "degraded",
  },
  {
    id: "gre4", name: "gre-msk-sgp", serverId: "srv1",
    localAddress: "10.0.0.1", remoteAddress: "10.0.4.1",
    localInnerIp: "10.200.0.13/30", remoteInnerIp: "10.200.0.14/30", poolId: "gp1",
    ipsec: defaultIpsec("qA4^eU9#wG1oXi6"),
    mtu: 1476, keepaliveInterval: 10, keepaliveRetries: 10,
    dscp: "inherit", clampTcpMss: true, allowFastPath: true,
    comment: "MSK → SGP core interconnect", enabled: false, status: "down",
  },
  {
    id: "gre5", name: "gre-lab-core", serverId: "srv7",
    localAddress: "10.0.0.7", remoteAddress: "10.0.0.1",
    localInnerIp: "10.201.0.1/30", remoteInnerIp: "10.201.0.2/30", poolId: "gp2",
    ipsec: null,
    mtu: 1500, keepaliveInterval: 0, keepaliveRetries: 0,
    dscp: "inherit", clampTcpMss: false, allowFastPath: true,
    comment: "Lab → core (internal, no IPsec)", enabled: true, status: "up",
  },
  {
    id: "gre6", name: "gre-ams-test", serverId: "srv6",
    localAddress: "10.0.3.2", remoteAddress: "10.0.3.1",
    localInnerIp: "10.201.0.5/30", remoteInnerIp: "10.201.0.6/30", poolId: "gp2",
    ipsec: null,
    mtu: 1476, keepaliveInterval: 5, keepaliveRetries: 5,
    dscp: 0, clampTcpMss: true, allowFastPath: true,
    comment: "AMS test → AMS edge", enabled: true, status: "up",
  },
]

// ─── Filter Rules (Community → Gateway per server) ────────────────────────────

export interface FilterRule {
  id: string
  community: string        // BGP community, e.g. "65001:100"
  communityName?: string   // optional human-readable name
  action?: "route" | "blackhole"  // default "route"; "blackhole" → null-route (RTBH)
  gateway: string          // next-hop IP for filter rule; empty for blackhole
  /** GRE: id туннеля / имя интерфейса; рекурсивный маршрут: `rec:<id>` строки recursive_routes на сервере */
  gatewayTunnelId: string
  description: string
}

export interface ServerFilterRuleset {
  serverId: string
  rules: FilterRule[]
}

export const serverFilterRulesets: ServerFilterRuleset[] = [
  // srv1 — mt-msk-core-01 (jump-host, MSK): gre1=SPB, gre2=FRA, gre3=AMS(deg), gre4=SGP(down)
  {
    serverId: "srv1",
    rules: [
      { id: "r1",  community: "65001:100", communityName: "youtube-bypass",     gateway: "10.200.0.6",  gatewayTunnelId: "gre2", description: "YouTube/Google Video → Frankfurt (IX)" },
      { id: "r2",  community: "65001:200", communityName: "streaming-eu",        gateway: "10.200.0.6",  gatewayTunnelId: "gre2", description: "Netflix, Twitch EU → Frankfurt" },
      { id: "r3",  community: "65001:300", communityName: "cdn-bypass",          gateway: "10.200.0.2",  gatewayTunnelId: "gre1", description: "Cloudflare / Akamai / Fastly → SPB" },
      { id: "r4",  community: "65002:100", communityName: "cdn-secondary",       gateway: "10.200.0.10", gatewayTunnelId: "gre3", description: "CDN резерв → Amsterdam (degraded)" },
      { id: "r5",  community: "65001:400", communityName: "office-direct",       gateway: "10.200.0.2",  gatewayTunnelId: "gre1", description: "MS Office 365 / Teams → SPB direct" },
      { id: "r6",  community: "65001:500", communityName: "gaming-ll",           gateway: "10.200.0.2",  gatewayTunnelId: "gre1", description: "Discord / Steam / Epic — низкая задержка → SPB" },
      { id: "r10", community: "65535:666", communityName: "BLACKHOLE (RFC 7999)", action: "blackhole",    gateway: "",            gatewayTunnelId: "",     description: "RTBH — null-route входящих маршрутов" },
      { id: "r11", community: "65001:666", communityName: "blackhole-local",      action: "blackhole",    gateway: "",            gatewayTunnelId: "",     description: "Локальная блокировка — сброс трафика" },
    ],
  },
  // srv7 — mt-msk-lab-01 (jump-host, MSK lab): gre5=core
  {
    serverId: "srv7",
    rules: [
      { id: "r7",  community: "65001:100", communityName: "youtube-bypass",     gateway: "10.201.0.2",  gatewayTunnelId: "gre5", description: "Lab: YouTube → core" },
      { id: "r8",  community: "65007:999", communityName: "school-block",        gateway: "10.201.0.2",  gatewayTunnelId: "gre5", description: "Lab: школьная блокировка" },
    ],
  },
  // srv6 — mt-ams-test-01 (jump-host, AMS test): gre6=AMS edge
  {
    serverId: "srv6",
    rules: [
      { id: "r9",  community: "65001:300", communityName: "cdn-bypass",         gateway: "10.201.0.6",  gatewayTunnelId: "gre6", description: "AMS test: CDN → AMS edge" },
    ],
  },
  // Exit nodes — нет правил по умолчанию
  { serverId: "srv2", rules: [] },
  { serverId: "srv3", rules: [] },
  { serverId: "srv4", rules: [] },
  { serverId: "srv5", rules: [] },
]

// ─── VXLAN mock data ─────────────────────────────────────────────────────────

export const vxlanTunnels: VxlanTunnel[] = [
  {
    id: "vx1", name: "vxlan-overlay-msk", vni: 10010, port: 0, dstPort: 8472,
    serverId: "srv1", vtepIp: "10.0.0.1", remoteVteps: ["10.0.1.1","10.0.2.1"],
    l2mtu: 1500, arpProxy: true, macLearning: true,
    comment: "MSK overlay — сегмент bypass", enabled: true, status: "up",
  },
  {
    id: "vx2", name: "vxlan-overlay-spb", vni: 10010, port: 0, dstPort: 8472,
    serverId: "srv2", vtepIp: "10.0.1.1", remoteVteps: ["10.0.0.1","10.0.2.1"],
    l2mtu: 1500, arpProxy: true, macLearning: true,
    comment: "SPB overlay — сегмент bypass", enabled: true, status: "up",
  },
  {
    id: "vx3", name: "vxlan-overlay-fra", vni: 10010, port: 0, dstPort: 8472,
    serverId: "srv3", vtepIp: "10.0.2.1", remoteVteps: ["10.0.0.1","10.0.1.1"],
    l2mtu: 1500, arpProxy: true, macLearning: false,
    comment: "FRA overlay — сегмент bypass", enabled: true, status: "up",
  },
  {
    id: "vx4", name: "vxlan-mgmt-lab", vni: 20001, port: 0, dstPort: 4789,
    serverId: "srv7", vtepIp: "10.0.0.7", remoteVteps: ["10.0.0.1"],
    l2mtu: 1500, arpProxy: false, macLearning: true,
    comment: "Lab management VXLAN", enabled: true, status: "up",
  },
  {
    id: "vx5", name: "vxlan-overlay-ams", vni: 10010, port: 0, dstPort: 8472,
    serverId: "srv4", vtepIp: "10.0.3.1", remoteVteps: ["10.0.0.1"],
    l2mtu: 1500, arpProxy: true, macLearning: true,
    comment: "AMS overlay (degraded)", enabled: true, status: "down",
  },
]

// ─── Container mock data ─────────────────────────────────────────────────────

export const routerContainers: RouterContainer[] = [
  {
    id: "c1", name: "adguard-msk", serverId: "srv1",
    image: "adguard/adguardhome", tag: "latest",
    status: "running",
    envs: [{ key: "AGH_CONFIG", value: "/opt/adguardhome/conf/AdGuardHome.yaml" }],
    mounts: [{ dst: "/opt/adguardhome/conf", src: "/disk1/adguard" }, { dst: "/opt/adguardhome/work", src: "/disk1/adguard-work" }],
    interfaces: ["veth-adguard"],
    startOnBoot: true, comment: "AdGuard Home — DNS фильтрация",
    uptime: "12д 4ч", cpu: 3, memMb: 64,
  },
  {
    id: "c2", name: "prometheus-msk", serverId: "srv1",
    image: "prom/prometheus", tag: "v2.52.0",
    status: "running",
    envs: [],
    mounts: [{ dst: "/prometheus", src: "/disk1/prom-data" }],
    interfaces: ["veth-prom"],
    cmd: "--config.file=/etc/prometheus/prometheus.yml --storage.tsdb.retention.time=30d",
    startOnBoot: true, comment: "Prometheus метрики",
    uptime: "5д 11ч", cpu: 8, memMb: 256,
  },
  {
    id: "c3", name: "grafana-msk", serverId: "srv1",
    image: "grafana/grafana", tag: "10.4.2",
    status: "running",
    envs: [{ key: "GF_SECURITY_ADMIN_PASSWORD", value: "*** (hidden)" }],
    mounts: [{ dst: "/var/lib/grafana", src: "/disk1/grafana" }],
    interfaces: ["veth-grafana"],
    startOnBoot: true, comment: "Grafana — дашборды мониторинга",
    uptime: "5д 11ч", cpu: 5, memMb: 128,
  },
  {
    id: "c4", name: "wg-portal-spb", serverId: "srv2",
    image: "wgportal/wg-portal", tag: "v1.3.1",
    status: "running",
    envs: [{ key: "WG_PORTAL_ADMIN_USER", value: "admin" }],
    mounts: [{ dst: "/app/data", src: "/disk1/wgportal" }],
    interfaces: ["veth-wgportal"],
    startOnBoot: true, comment: "WireGuard Portal — управление клиентами",
    uptime: "3д 7ч", cpu: 1, memMb: 48,
  },
  {
    id: "c5", name: "unbound-fra", serverId: "srv3",
    image: "mvance/unbound", tag: "1.19.3",
    status: "stopped",
    envs: [],
    mounts: [],
    interfaces: ["veth-unbound"],
    startOnBoot: false, comment: "Unbound DNS резолвер (в резерве)",
    cpu: 0, memMb: 0,
  },
]

// ─── Certificate mock data ────────────────────────────────────────────────────

export const routerCertificates: RouterCertificate[] = [
  {
    id: "cert1", name: "mt-msk-core-01-server", serverId: "srv1",
    commonName: "mt-msk-core-01.routerlists.io",
    sans: ["mt-msk-core-01.routerlists.io","10.0.0.1"],
    issuedBy: "MikrotikManager Internal CA", validFrom: "2024-01-15",
    validUntil: "2026-01-15", daysLeft: 261,
    keySize: 4096, usage: ["server"], trusted: true, status: "valid",
  },
  {
    id: "cert2", name: "routerlists-internal-ca", serverId: "srv1",
    commonName: "MikrotikManager Internal CA",
    sans: [],
    issuedBy: "MikrotikManager Internal CA (self-signed)", validFrom: "2023-06-01",
    validUntil: "2033-06-01", daysLeft: 2589,
    keySize: 4096, usage: ["ca","crl-sign"], trusted: true, status: "valid",
  },
  {
    id: "cert3", name: "mt-spb-edge-01-server", serverId: "srv2",
    commonName: "mt-spb-edge-01.routerlists.io",
    sans: ["mt-spb-edge-01.routerlists.io","10.0.1.1"],
    issuedBy: "MikrotikManager Internal CA", validFrom: "2024-01-15",
    validUntil: "2026-01-15", daysLeft: 261,
    keySize: 4096, usage: ["server"], trusted: true, status: "valid",
  },
  {
    id: "cert4", name: "mt-fra-edge-01-server", serverId: "srv3",
    commonName: "mt-fra-edge-01.routerlists.io",
    sans: ["mt-fra-edge-01.routerlists.io","10.0.2.1"],
    issuedBy: "Let's Encrypt", validFrom: "2026-01-10",
    validUntil: "2026-04-10", daysLeft: -19,
    keySize: 2048, usage: ["server"], trusted: true, status: "expired",
  },
  {
    id: "cert5", name: "wg-client-admin", serverId: "srv1",
    commonName: "admin.routerlists.io",
    sans: ["admin.routerlists.io"],
    issuedBy: "MikrotikManager Internal CA", validFrom: "2025-06-01",
    validUntil: "2026-06-01", daysLeft: 33,
    keySize: 2048, usage: ["client"], trusted: true, status: "valid",
  },
  {
    id: "cert6", name: "mt-ams-edge-01-server", serverId: "srv4",
    commonName: "mt-ams-edge-01.routerlists.io",
    sans: ["mt-ams-edge-01.routerlists.io"],
    issuedBy: "MikrotikManager Internal CA", validFrom: "2024-04-01",
    validUntil: "2026-05-15", daysLeft: 16,
    keySize: 2048, usage: ["server"], trusted: false, status: "valid",
  },
  {
    id: "cert7", name: "mt-msk-lab-01-server", serverId: "srv7",
    commonName: "mt-msk-lab-01.routerlists.io",
    sans: ["mt-msk-lab-01.routerlists.io","10.0.0.7"],
    issuedBy: "MikrotikManager Internal CA", validFrom: "2025-09-01",
    validUntil: "2026-09-01", daysLeft: 125,
    keySize: 4096, usage: ["server"], trusted: true, status: "valid",
  },
]
