import { eq } from "drizzle-orm"
import { db } from "../../db/index.js"
import { alertEngineConfirmPending } from "../../db/schema.js"
import type { ApiAlertRule } from "../alerts-service.js"
import type { RuleEvalHit } from "./types.js"

export function deleteConfirmPending(ruleId: string) {
  db.delete(alertEngineConfirmPending).where(eq(alertEngineConfirmPending.ruleId, ruleId)).run()
}

/**
 * Обновляет состояние ожидания стабильности и возвращает, можно ли отправлять уведомление в этом тике.
 * При отсутствии срабатывания (`hit == null`) ожидание сбрасывается.
 */
export function stabilityReadyForSend(
  ruleId: string,
  hit: RuleEvalHit | null,
  delaySec: number | null | undefined,
): boolean {
  if (!hit) {
    deleteConfirmPending(ruleId)
    return false
  }
  const sec = delaySec != null && delaySec > 0 ? Math.floor(delaySec) : 0
  if (sec <= 0) {
    deleteConfirmPending(ruleId)
    return true
  }

  const now = Date.now()
  const nowIso = new Date().toISOString()
  const existing = db
    .select()
    .from(alertEngineConfirmPending)
    .where(eq(alertEngineConfirmPending.ruleId, ruleId))
    .limit(1)
    .all()[0]

  if (!existing || existing.payloadHash !== hit.payloadHash) {
    if (existing) {
      db.update(alertEngineConfirmPending)
        .set({ payloadHash: hit.payloadHash, sinceAt: nowIso })
        .where(eq(alertEngineConfirmPending.ruleId, ruleId))
        .run()
    } else {
      db.insert(alertEngineConfirmPending).values({ ruleId, payloadHash: hit.payloadHash, sinceAt: nowIso }).run()
    }
    return false
  }

  const t = Date.parse(existing.sinceAt)
  if (!Number.isFinite(t)) return false
  return now - t >= sec * 1000
}

/** После успешной отправки — сбросить таймер стабильности для следующего цикла. */
export function clearConfirmPendingAfterSend(ruleIds: string[]) {
  for (const id of ruleIds) deleteConfirmPending(id)
}

export function computeStabilityReadyMap(
  rules: ApiAlertRule[],
  hitByRule: Map<string, RuleEvalHit | null>,
): Map<string, boolean> {
  const m = new Map<string, boolean>()
  for (const rule of rules) {
    if (!rule.enabled) {
      deleteConfirmPending(rule.id)
      m.set(rule.id, false)
      continue
    }
    const hit = hitByRule.get(rule.id) ?? null
    const delaySec =
      hit?.transition === "recovery"
        ? rule.recoveryMode === "conditional"
          ? rule.recoveryStabilitySec
          : 0
        : rule.confirmStabilitySec
    m.set(rule.id, stabilityReadyForSend(rule.id, hit, delaySec))
  }
  return m
}
