/**
 * Login failure throttling — foundation-auth-rbac (Task 12).
 *
 * KV-counter based, keyed by email. Exponential backoff after 5 failures,
 * hard lockout after 10. This complements the IP-level RATE_LIMITER_AUTH
 * binding (which caps raw attempt volume); this layer defends a single account
 * against credential stuffing across rotating IPs.
 *
 * Counter TTL is 15 minutes — a quiet window resets the account automatically.
 */
import type { Env } from '@zync/types'

const WINDOW_SECONDS = 15 * 60
const BACKOFF_THRESHOLD = 5
const LOCKOUT_THRESHOLD = 10

function key(email: string): string {
  return `login_fail:${email.toLowerCase()}`
}

async function readCount(env: Env, email: string): Promise<number> {
  const raw = await env.KV.get(key(email))
  const n = raw ? Number(raw) : 0
  return Number.isFinite(n) ? n : 0
}

/** Record a failed attempt; returns the new failure count. */
export async function recordFailure(env: Env, email: string): Promise<number> {
  const next = (await readCount(env, email)) + 1
  await env.KV.put(key(email), String(next), { expirationTtl: WINDOW_SECONDS })
  return next
}

/** Clear the failure counter on a successful login. */
export async function clearFailures(env: Env, email: string): Promise<void> {
  await env.KV.delete(key(email))
}

/** True once the account has hit the hard lockout threshold (10 failures). */
export async function isLockedOut(env: Env, email: string): Promise<boolean> {
  return (await readCount(env, email)) >= LOCKOUT_THRESHOLD
}

/**
 * Backoff delay (seconds) to advise after the current failure count. 0 below
 * the backoff threshold; doubles each failure thereafter (capped at the window).
 */
export function backoffSeconds(failures: number): number {
  if (failures < BACKOFF_THRESHOLD) return 0
  const delay = 2 ** (failures - BACKOFF_THRESHOLD)
  return Math.min(delay, WINDOW_SECONDS)
}
