import { db, sqliteDatabase } from "../db/index.js"
import { alertBgpPeerSamples, alertGreTunnelSamples } from "../db/schema.js"
import { bgpPeerAlertKey, fetchBgpSessionsForAlerts } from "./bgp-peers-live.js"
import { fetchGreTunnelLiveRows } from "./gre-tunnels-live.js"
import type { GreBgpSnapshotRunSnapshot } from "../types/scheduler-run-snapshot.js"
import { SCHEDULER_RUN_SNAPSHOT_VERSION } from "../types/scheduler-run-snapshot.js"

let collecting = false

export function getGreBgpSnapshotCollectorState(): { running: boolean } {
  return { running: collecting }
}

/**
 * Один опрос GRE + BGP по включённым серверам и запись строк в SQLite для `buildSignalSnapshot`.
 * Движок оповещений больше не дублирует эти REST-запросы.
 */
export async function collectGreBgpSnapshotOnce(): Promise<GreBgpSnapshotRunSnapshot> {
  const sampledAt = new Date().toISOString()
  if (collecting) {
    return {
      v: SCHEDULER_RUN_SNAPSHOT_VERSION,
      job: "gre_bgp",
      sampledAt,
      skipped: true,
      greWritten: 0,
      bgpWritten: 0,
      errors: [],
    }
  }
  collecting = true
  const errors: string[] = []
  const snapshot: GreBgpSnapshotRunSnapshot = {
    v: SCHEDULER_RUN_SNAPSHOT_VERSION,
    job: "gre_bgp",
    sampledAt,
    greWritten: 0,
    bgpWritten: 0,
    greTunnels: [],
    bgpPeers: [],
    errors: [],
  }

  try {
    const [greSettled, bgpSettled] = await Promise.allSettled([
      fetchGreTunnelLiveRows(),
      fetchBgpSessionsForAlerts(),
    ])

    if (greSettled.status === "rejected") {
      const msg =
        greSettled.reason instanceof Error ? greSettled.reason.message : String(greSettled.reason)
      errors.push(`GRE: ${msg}`)
    }
    if (bgpSettled.status === "rejected") {
      const msg =
        bgpSettled.reason instanceof Error ? bgpSettled.reason.message : String(bgpSettled.reason)
      errors.push(`BGP: ${msg}`)
    }

    const greRows = greSettled.status === "fulfilled" ? greSettled.value : []
    const bgpRows = bgpSettled.status === "fulfilled" ? bgpSettled.value : []
    snapshot.greTunnels = greRows.map((r) => ({ targetLabel: r.targetLabel, status: r.status }))
    snapshot.bgpPeers = bgpRows.map((s) => ({ key: bgpPeerAlertKey(s), state: s.state }))

    db.transaction((tx) => {
      for (const r of greRows) {
        tx.insert(alertGreTunnelSamples).values({
          sampledAt,
          targetLabel: r.targetLabel,
          status: r.status,
        }).run()
        snapshot.greWritten += 1
      }
      for (const s of bgpRows) {
        tx.insert(alertBgpPeerSamples).values({
          sampledAt,
          peerKey: bgpPeerAlertKey(s),
          state: s.state,
        }).run()
        snapshot.bgpWritten += 1
      }
    })

    sqliteDatabase
      .prepare(`DELETE FROM alert_gre_tunnel_samples WHERE sampled_at < datetime('now', '-30 days')`)
      .run()
    sqliteDatabase
      .prepare(`DELETE FROM alert_bgp_peer_samples WHERE sampled_at < datetime('now', '-30 days')`)
      .run()

    if (errors.length) snapshot.errors = errors
  } catch (e) {
    const msg = e instanceof Error ? e.message : String(e)
    snapshot.fatalError = msg
  } finally {
    collecting = false
  }
  return snapshot
}
