/**
 * Снимок результатов одного прогона планировщика (JSON в `scheduler_runs.result_json`).
 * Версия `v` для совместимости при расширении схемы.
 */

export const SCHEDULER_RUN_SNAPSHOT_VERSION = 1 as const

export interface TrafficServerSnapshot {
  serverId: number
  name: string
  host: string
  ok: boolean
  error?: string
  /** Сколько интерфейсов записано в сэмплы */
  interfaces?: number
  /** Сумма RX по интерфейсам, Мбит/с (округл.) */
  sumRxMbps?: number
  /** Сумма TX по интерфейсам, Мбит/с (округл.) */
  sumTxMbps?: number
}

export interface TrafficRunSnapshot {
  v: typeof SCHEDULER_RUN_SNAPSHOT_VERSION
  job: "traffic"
  sampledAt: string
  /** Прогон пропущен — предыдущий сбор ещё выполняется */
  skipped?: boolean
  /** Критическая ошибка до/вне цикла по серверам */
  fatalError?: string
  servers: TrafficServerSnapshot[]
}

export interface ResourceServerSnapshot {
  serverId: number
  name: string
  host: string
  status: "online" | "offline"
  error?: string
  cpuLoadPct?: number
  memUsedMb?: number
  memTotalMb?: number
  memUsedPct?: number
  diskFreeMb?: number
  diskTotalMb?: number
  uptimeSeconds?: number
  boardName?: string
  rosVersion?: string
}

export interface ResourcesRunSnapshot {
  v: typeof SCHEDULER_RUN_SNAPSHOT_VERSION
  job: "uptime_resources"
  sampledAt: string
  skipped?: boolean
  fatalError?: string
  servers: ResourceServerSnapshot[]
}

export interface PingProbeSnapshot {
  probeId: string
  name: string
  target: string
  srcServerId: number
  srcServerName: string
  srcInterface: string
  ok: boolean
  rttMs: number | null
  lossPct: number
  status: "up" | "warn" | "down"
  error?: string
}

export interface PingRunSnapshot {
  v: typeof SCHEDULER_RUN_SNAPSHOT_VERSION
  job: "uptime_ping"
  sampledAt: string
  skipped?: boolean
  fatalError?: string
  /** Пробы, для которых в этом тике записан сэмпл (не пропущены по interval) */
  probes: PingProbeSnapshot[]
  /** Сколько проб пропущено из‑за interval_sec */
  skippedByInterval?: number
}

export interface SpeedRunSnapshot {
  probeId: string
  srcServerId: number
  srcServerName: string
  dstServerId: number
  dstServerName: string
  srcInterface: string
  dstInterface: string
  protocol: string
  direction: string
  durationSec: number
  ok: boolean
  txAvgMbps?: number | null
  rxAvgMbps?: number | null
  pingRttMs?: number | null
  pingLossPct?: number | null
  pingError?: string | null
  error?: string
}

export interface SpeedScheduledRunSnapshot {
  v: typeof SCHEDULER_RUN_SNAPSHOT_VERSION
  job: "uptime_speed"
  sampledAt: string
  runs: SpeedRunSnapshot[]
}

/** Узел каталога: успешный GET `/system/identity` (REST) и время ответа. */
export interface ServerRestPingSnapshot {
  serverId: number
  name: string
  host: string
  ok: boolean
  /** RTT успешного REST-запроса, мс */
  latencyMs?: number | null
  error?: string
}

export interface ServersRestPingRunSnapshot {
  v: typeof SCHEDULER_RUN_SNAPSHOT_VERSION
  job: "servers_rest_ping"
  sampledAt: string
  skipped?: boolean
  fatalError?: string
  servers: ServerRestPingSnapshot[]
}

/** Одна строка диагностики прогона движка (для `scheduler_runs.result_json`). */
export type AlertEngineRuleDiagSnapshot = {
  ruleId: string
  inGroup: boolean
  evalHit: boolean
  hitTransition?: "problem" | "recovery" | "neutral"
  hitMessage?: string
  stabilityOk: boolean
  cooldownOk: boolean
  telegramOk: boolean
  blocked?:
    | "no_hit"
    | "stability"
    | "cooldown"
    | "no_telegram"
    | "dedupe_positive"
    | "in_group"
}

export interface AlertEngineRunSnapshot {
  v: typeof SCHEDULER_RUN_SNAPSHOT_VERSION
  job: "alert_engine"
  sampledAt: string
  rulesChecked: number
  standaloneFires: number
  groupFires: number
  skippedNoTelegram: boolean
  errors?: string[]
  /** Почему правило не дало отдельную отправку в этом тике (если массив пуст — движок без правил). */
  ruleDiag?: AlertEngineRuleDiagSnapshot[]
}

/** Снимок джобы `gre_bgp`: запись GRE/BGP в SQLite для алерт-движка. */
export interface GreBgpSnapshotRunSnapshot {
  v: typeof SCHEDULER_RUN_SNAPSHOT_VERSION
  job: "gre_bgp"
  sampledAt: string
  skipped?: boolean
  fatalError?: string
  greWritten: number
  bgpWritten: number
  /** Текущее состояние GRE на момент прогона (для alert_engine). */
  greTunnels?: Array<{
    targetLabel: string
    status: "up" | "down" | "degraded"
  }>
  /** Текущее состояние BGP-пиров на момент прогона (для alert_engine). */
  bgpPeers?: Array<{
    key: string
    state: string
  }>
  errors?: string[]
}

export interface InternetPathRunSnapshot {
  v: typeof SCHEDULER_RUN_SNAPSHOT_VERSION
  job: "internet_path"
  sampledAt: string
  homes: number
  snapshotSaved: boolean
  fatalError?: string
}

export interface CertificatesRenewTargetSnapshot {
  serverId: string
  certName: string
  action: "ok" | "renewed" | "skipped" | "error"
  daysLeft: number | null
  message: string
}

export interface CertificatesRenewRunSnapshot {
  v: typeof SCHEDULER_RUN_SNAPSHOT_VERSION
  job: "certificates_renew"
  sampledAt: string
  skipped?: boolean
  fatalError?: string
  checked: number
  renewed: number
  skippedTargets: number
  errors: string[]
  targets?: CertificatesRenewTargetSnapshot[]
}

export interface BackupsRunSnapshot {
  v: typeof SCHEDULER_RUN_SNAPSHOT_VERSION
  job: "backups"
  sampledAt: string
  skipped?: boolean
  due: boolean
  created: number
  failures: number
  pruned: number
  errors?: string[]
  fatalError?: string
}

export type SchedulerRunSnapshot =
  | TrafficRunSnapshot
  | ResourcesRunSnapshot
  | PingRunSnapshot
  | SpeedScheduledRunSnapshot
  | ServersRestPingRunSnapshot
  | GreBgpSnapshotRunSnapshot
  | InternetPathRunSnapshot
  | CertificatesRenewRunSnapshot
  | BackupsRunSnapshot
  | AlertEngineRunSnapshot
