/**
 * Внутренние хуки: после записи сигналов в SQLite (коллекторы) — отложенный прогон `alert_engine`.
 * Не импортирует `scheduler.ts` (избегаем цикла); runner задаётся через `wireAlertEngineRunner`.
 *
 * Любой код, пишущий таблицы для `buildSignalSnapshot`, после успешного коммита должен вызывать
 * `scheduleAlertEngineAfterDataCollectors()`.
 */
import { isSchedulerJobRunning } from "./scheduler-running.js"

const ALERT_AFTER_COLLECT_DEBOUNCE_MS = 250
const ALERT_AFTER_COLLECT_WAIT_MS = 100

let alertAfterCollectTimer: ReturnType<typeof setTimeout> | null = null
let alertAfterCollectChain: Promise<void> = Promise.resolve()

let alertEngineRunner: (() => Promise<void>) | null = null

/** Задать runner один раз при старте приложения (обычно `() => executeSchedulerJob("alert_engine")`). */
export function wireAlertEngineRunner(run: () => Promise<void>): void {
  alertEngineRunner = run
}

export function clearAlertCollectorHooksTimer(): void {
  if (alertAfterCollectTimer != null) {
    clearTimeout(alertAfterCollectTimer)
    alertAfterCollectTimer = null
  }
}

async function runAlertEngineWhenIdle(): Promise<void> {
  const run = alertEngineRunner
  if (!run) return
  while (isSchedulerJobRunning("alert_engine")) {
    await new Promise<void>((resolve) => setTimeout(resolve, ALERT_AFTER_COLLECT_WAIT_MS))
  }
  await run()
}

/** После успешной записи сигналов в БД коллекторами (не из `alert_engine`). */
export function scheduleAlertEngineAfterDataCollectors(): void {
  if (alertAfterCollectTimer != null) clearTimeout(alertAfterCollectTimer)
  alertAfterCollectTimer = setTimeout(() => {
    alertAfterCollectTimer = null
    alertAfterCollectChain = alertAfterCollectChain
      .then(() => runAlertEngineWhenIdle())
      .catch(() => {})
  }, ALERT_AFTER_COLLECT_DEBOUNCE_MS)
}
