/**
 * Разбор полей /system/resource из RouterOS REST: не всегда «сырые» байты в виде десятичной строки.
 * На железе часто встречаются значения вида "224.0MiB", "94.2MiB"; parseInt от этого даёт мусор или 0.
 */

export function parseRosDataSizeBytes(raw: unknown): number {
  if (raw == null) return 0
  if (typeof raw === "number" && Number.isFinite(raw)) return Math.max(0, Math.floor(raw))
  let s = String(raw).trim().replace(/\s+/g, "")
  if (!s) return 0
  if (/^\d+$/.test(s)) {
    const n = Number.parseInt(s, 10)
    return Number.isFinite(n) ? Math.max(0, n) : 0
  }
  const m = s.match(/^(\d+(?:[.,]\d+)?)(KiB|MiB|GiB|TiB|Ki|Mi|Gi|Ti|KB|MB|GB|TB)$/i)
  if (m) {
    const v = Number.parseFloat(m[1].replace(",", "."))
    if (!Number.isFinite(v) || v < 0) return 0
    const u = m[2].toLowerCase()
    const mult =
      u === "ki" || u === "kib" || u === "kb" ? 1024
        : u === "mi" || u === "mib" || u === "mb" ? 1024 ** 2
          : u === "gi" || u === "gib" || u === "gb" ? 1024 ** 3
            : u === "ti" || u === "tib" || u === "tb" ? 1024 ** 4
              : 1
    return Math.max(0, Math.floor(v * mult))
  }
  const fallback = Number.parseInt(s, 10)
  return Number.isFinite(fallback) ? Math.max(0, fallback) : 0
}

/** cpu-load: "7%", "7", 7 */
export function parseRosCpuLoadPercent(raw: unknown): number {
  if (raw == null) return 0
  if (typeof raw === "number" && Number.isFinite(raw)) {
    return Math.min(100, Math.max(0, Math.round(raw)))
  }
  const s = String(raw).trim().replace("%", "").replace(",", ".").trim()
  if (!s) return 0
  const n = Number.parseFloat(s)
  if (!Number.isFinite(n)) return 0
  return Math.min(100, Math.max(0, Math.round(n)))
}

/**
 * `uptime` из /system/resource (REST): обычно "2d20h12m20s", "39m", "29s".
 * Встречаются варианты: только секунды строкой, `d.hh:mm:ss`, `hh:mm:ss` без суффиксов.
 * @see https://help.mikrotik.com/docs/display/ROS/Resource
 */
export function parseRosUptimeToSeconds(raw: unknown): number {
  if (raw == null) return 0
  if (typeof raw === "number" && Number.isFinite(raw)) {
    return Math.max(0, Math.floor(raw))
  }
  const s0 = String(raw).trim().replace(/\u00a0/g, " ").trim()
  if (!s0) return 0

  // Только десятичные цифры — секунды (некоторые клиенты/прокси)
  if (/^\d+$/.test(s0)) {
    const n = Number.parseInt(s0, 10)
    return Number.isFinite(n) ? Math.max(0, n) : 0
  }

  const s = s0.toLowerCase().replace(/\s+/g, "")

  // 1d18:27:15
  const dClock = s.match(/^(\d+)d(\d{1,3}):(\d{2}):(\d{2})$/i)
  if (dClock) {
    const d = Number.parseInt(dClock[1], 10)
    const hh = Number.parseInt(dClock[2], 10)
    const mm = Number.parseInt(dClock[3], 10)
    const ss = Number.parseInt(dClock[4], 10)
    if ([d, hh, mm, ss].every((x) => Number.isFinite(x) && x >= 0)) {
      return d * 86400 + hh * 3600 + mm * 60 + ss
    }
  }

  // 18:27:15 — только если нет суффиксов w/d/h/m/s (иначе это часть "2d20h12m20s")
  if (!/[wdhms]/i.test(s0) && /^\d{1,7}:\d{2}:\d{2}$/.test(s)) {
    const p = s.split(":")
    if (p.length === 3) {
      const hh = Number.parseInt(p[0], 10)
      const mm = Number.parseInt(p[1], 10)
      const sec = Number.parseInt(p[2], 10)
      if ([hh, mm, sec].every((x) => Number.isFinite(x) && x >= 0)) {
        return hh * 3600 + mm * 60 + sec
      }
    }
  }

  let total = 0
  for (const m of s.matchAll(/(\d+)(w|d|h|m(?!s)|s)/gi)) {
    const n = Number.parseInt(m[1], 10)
    if (!Number.isFinite(n) || n < 0) continue
    const u = m[2].toLowerCase()
    switch (u) {
      case "w": total += n * 604800; break
      case "d": total += n * 86400; break
      case "h": total += n * 3600; break
      case "m": total += n * 60; break
      case "s": total += n; break
      default: break
    }
  }
  return Math.max(0, total)
}
