import assert from "node:assert/strict"
import {
  markIfaceRefreshAttempt,
  rememberServerIfaces,
  resetIfaceCacheForTests,
  shouldRefreshIfaces,
} from "./traffic-flow-ifindex.js"
import {
  applyHeartbeatForTests,
  flushPendingForTests,
  getFlowListenerState,
  getFlowRuntimeCounters,
  getFlowWorkerHealth,
  ingestParsedFlowsForServerForTests,
  lastFlushUsedTransactionForTests,
  maybeRefreshIfaces,
  peekPendingFlows,
  resetFlowRingsForTests,
  setPendingCapForTests,
  setRefreshIfacesForTests,
  setWantListenForTests,
  simulateWorkerExitForTests,
} from "./traffic-flow-ingest.js"
import { configureEngine, droppedForTests, pendingSizeForTests } from "./traffic-flow-engine.js"
import { sqliteDatabase } from "../db/index.js"

resetIfaceCacheForTests()
resetFlowRingsForTests()

let refreshCalls = 0
setRefreshIfacesForTests(async () => {
  refreshCalls += 1
})

rememberServerIfaces(1, [{ ".id": "*A", name: "wg-flow" }])
assert.equal(shouldRefreshIfaces(1), false)
assert.equal(maybeRefreshIfaces(1), false)
assert.equal(refreshCalls, 0)

resetIfaceCacheForTests()
assert.equal(shouldRefreshIfaces(2), true)
assert.equal(maybeRefreshIfaces(2), true)
assert.equal(refreshCalls, 1)

markIfaceRefreshAttempt(2)
assert.equal(shouldRefreshIfaces(2), false)
assert.equal(maybeRefreshIfaces(2), false)
assert.equal(refreshCalls, 1)

assert.equal(lastFlushUsedTransactionForTests(), false)

resetFlowRingsForTests()
setPendingCapForTests(3)
const many = Array.from({ length: 6 }, (_, i) => ({
  src: `10.1.1.${i + 1}`,
  dst: "8.8.8.8",
  proto: 6,
  srcPort: 50000 + i,
  dstPort: 443,
  bytes: 1000,
  packets: 1,
  inIface: "2",
  outIface: "",
}))
ingestParsedFlowsForServerForTests(9, many)
assert.equal(pendingSizeForTests(), 3)
assert.equal(droppedForTests(), 3)
assert.equal(peekPendingFlows().length, 3)
setPendingCapForTests(null)

resetFlowRingsForTests()
configureEngine({ topN: 20 })
const talkers = Array.from({ length: 25 }, (_, i) => ({
  src: `10.2.1.${i + 1}`,
  dst: "1.1.1.1",
  proto: 6,
  srcPort: 40000 + i,
  dstPort: 443,
  bytes: 1000 + i,
  packets: 1,
  inIface: "2",
  outIface: "",
}))
ingestParsedFlowsForServerForTests(9, talkers)
flushPendingForTests()
const stored = sqliteDatabase.prepare(`
  SELECT COUNT(*) AS n FROM flow_buckets WHERE server_id = 9
`).get() as { n: number }
assert.ok(stored.n <= 20, `expected topN cap, got ${stored.n}`)
sqliteDatabase.prepare(`DELETE FROM flow_buckets WHERE server_id = 9`).run()
sqliteDatabase.prepare(`DELETE FROM flow_minute_stats WHERE server_id = 9`).run()
sqliteDatabase.prepare(`DELETE FROM flow_minute_dims WHERE server_id = 9`).run()
sqliteDatabase.prepare(`DELETE FROM flow_daily_dims WHERE server_id = 9`).run()

applyHeartbeatForTests({
  bound: true,
  address: "127.0.0.1:4739",
  packetsReceived: 42,
  lastExporterIp: "10.255.254.3",
  lastError: "",
  lastDatagramAt: new Date().toISOString(),
  pendingSize: 1,
  dropped: 0,
  rowsStored: 1,
  workerAlive: true,
  rings: [],
})
assert.equal(getFlowListenerState().bound, true)
assert.equal(getFlowRuntimeCounters().packetsReceived, 42)
assert.equal(getFlowWorkerHealth().alive, false)
setWantListenForTests(true)
assert.equal(simulateWorkerExitForTests(), 1)
assert.equal(getFlowListenerState().bound, false)
setWantListenForTests(false)

resetFlowRingsForTests()
resetIfaceCacheForTests()
setRefreshIfacesForTests(null)

console.log("traffic-flow-ingest.test.ts: ok")
