const IPV4 = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/

/** Нормализация IP/endpoint из RouterOS (CIDR, zone id) — как в network-map-layout. */
export function normalizeGreEndpointAddr(addr: string): string {
  return addr.trim().split("/")[0].split("%")[0].trim()
}

/** Явный IPv4 (для отличия от FQDN в remote-address GRE). */
export function isIpv4String(s: string): boolean {
  return IPV4.test(s.trim())
}

/**
 * Сопоставление IP WAN в каталоге с outer GRE: прямой IP или FQDN,
 * зарезолвенный в API (hostname lower-case → A-запись).
 */
export function wanUplinkIpMatchesGreOuter(
  wanIp: string,
  greOuter: string,
  resolvedIpv4ByHost?: ReadonlyMap<string, string>,
): boolean {
  const a = normalizeGreEndpointAddr(wanIp)
  const b = normalizeGreEndpointAddr(greOuter)
  if (!a || !b) return false
  if (a === b) return true
  if (resolvedIpv4ByHost) {
    const rb = resolvedIpv4ByHost.get(b.toLowerCase())
    if (rb && a === normalizeGreEndpointAddr(rb)) return true
    const ra = resolvedIpv4ByHost.get(a.toLowerCase())
    if (ra && b === normalizeGreEndpointAddr(ra)) return true
    if (ra && rb && normalizeGreEndpointAddr(ra) === normalizeGreEndpointAddr(rb)) return true
  }
  return false
}

/** Все варианты внешнего IP для сопоставления с каталогом (IP и зарезолвенный FQDN). */
export function greOuterComparableIps(
  outer: string,
  resolvedIpv4ByHost?: ReadonlyMap<string, string>,
): string[] {
  const n = normalizeGreEndpointAddr(outer)
  if (!n || n === "0.0.0.0") return []
  const out: string[] = []
  if (isIpv4String(n)) out.push(n)
  const r = resolvedIpv4ByHost?.get(n.toLowerCase())
  if (r) {
    const ip = normalizeGreEndpointAddr(r)
    if (ip && isIpv4String(ip) && !out.includes(ip)) out.push(ip)
  }
  return out
}

/** Собрать уникальные FQDN из local/remote-address (без чистых IPv4). */
export function collectGreEndpointHostnames(
  tunnels: Array<{ localAddress: string; remoteAddress: string }>,
): string[] {
  const set = new Set<string>()
  for (const t of tunnels) {
    for (const a of [t.localAddress, t.remoteAddress]) {
      const n = normalizeGreEndpointAddr(a)
      if (!n || n === "0.0.0.0") continue
      if (!isIpv4String(n)) set.add(n.toLowerCase())
    }
  }
  return [...set]
}

/** Ответ POST /api/network/resolve-hosts → Map для матчинга. */
export function greResolvedMapFromApi(
  results: Record<string, string | null> | undefined,
): ReadonlyMap<string, string> {
  const m = new Map<string, string>()
  if (!results) return m
  for (const [k, v] of Object.entries(results)) {
    if (v && isIpv4String(v)) m.set(k.toLowerCase(), normalizeGreEndpointAddr(v))
  }
  return m
}

/** Подпись outer на карте: при FQDN дополнительно показываем разрешённый IPv4. */
export function formatGreOuterForDisplay(
  addr: string,
  resolvedIpv4ByHost?: ReadonlyMap<string, string>,
): string {
  const n = normalizeGreEndpointAddr(addr) || "?"
  if (isIpv4String(n)) return n
  const r = resolvedIpv4ByHost?.get(n.toLowerCase())
  return r ? `${n} (${r})` : n
}
