/**
 * Commission-system (Laravel middleware) reachability probe with anti-flap hysteresis.
 *
 * Probes Laravel 12's built-in liveness route at the ROOT (`/up`, NOT under /api) —
 * it returns 200 whenever Laravel is serving requests, independent of business state.
 * (Do NOT probe /api/monitoring/health: it returns 503 on failed order imports even
 * when Laravel itself is up.)
 *
 * Anti-flapping: a short blip (single failed probe) must NOT flip the indicator.
 * We only report OFFLINE after >= 3 consecutive failed probes spanning >= 60s of
 * continuous unreachability; the FIRST successful probe flips back to ONLINE.
 * Raw probes are rate-limited to one per 15s (module cache) so client polling can
 * never hammer Laravel. State is per-process (PM2 instances: 1).
 */

const PROBE_TIMEOUT_MS = 3000
const MIN_PROBE_INTERVAL_MS = 15_000
const OFFLINE_AFTER_FAILURES = 3
const OFFLINE_AFTER_MS = 60_000

const state = {
  reportedOnline: true,
  consecutiveFailures: 0,
  firstFailureAt: 0,
  checkedAt: 0
}

// Share one in-flight probe between concurrent status requests
let probing: Promise<void> | null = null

const markReachable = () => {
  state.consecutiveFailures = 0
  state.firstFailureAt = 0
  state.reportedOnline = true
}

const rawProbe = async () => {
  const config = useRuntimeConfig()
  const now = Date.now()
  state.checkedAt = now
  try {
    await $fetch(config.api.laravel + '/up', { timeout: PROBE_TIMEOUT_MS })
    markReachable()
  } catch (err: any) {
    // Any real HTTP response that isn't a gateway/unavailable status proves the
    // backend stack answered (e.g. a deployment where /up 404s — dev-data does).
    // Only transport failures (timeout, refused, DNS) and 502/503/504 count as down.
    const status = Number(err?.status ?? err?.statusCode ?? err?.response?.status ?? 0)
    if (status > 0 && status !== 502 && status !== 503 && status !== 504) {
      markReachable()
      return
    }
    state.consecutiveFailures += 1
    if (state.firstFailureAt === 0) state.firstFailureAt = now
    if (
      state.consecutiveFailures >= OFFLINE_AFTER_FAILURES &&
      now - state.firstFailureAt >= OFFLINE_AFTER_MS
    ) {
      state.reportedOnline = false
    }
  }
}

export const probeCommissionSystem = async (): Promise<{
  online: boolean
  checkedAt: number
  degradedSince: number | null
}> => {
  try {
    if (Date.now() - state.checkedAt >= MIN_PROBE_INTERVAL_MS) {
      if (!probing) {
        probing = rawProbe().finally(() => { probing = null })
      }
      await probing
    }
  } catch {
    // fail-soft — keep the last reported state
  }
  return {
    online: state.reportedOnline,
    checkedAt: state.checkedAt,
    degradedSince: state.firstFailureAt > 0 ? state.firstFailureAt : null
  }
}
