// Failed-login lockout: 5 wrong passwords for an email within 15 minutes locks
// that email for 15 minutes, from any device. The password is deliberately
// short, so this is what stops someone guessing it. Kept in memory: a container
// restart clears it, which is fine for a one-household app.

const MAX_FAILURES = 5
const WINDOW_MS = 15 * 60 * 1000

const failures = new Map<string, { count: number; lastAt: number; lockedUntil: number }>()

/** Minutes left on the lock for this email, or 0 if it may try. */
export function lockedMinutes(email: string): number {
  const entry = failures.get(email)
  if (!entry || entry.lockedUntil <= Date.now()) return 0
  return Math.ceil((entry.lockedUntil - Date.now()) / 60000)
}

export function recordFailure(email: string) {
  const now = Date.now()
  // Guesses at made-up emails land here too; drop stale entries so the map
  // can't grow without bound.
  if (failures.size > 1000) {
    for (const [key, e] of failures) if (now - e.lastAt > WINDOW_MS && e.lockedUntil <= now) failures.delete(key)
  }
  const entry = failures.get(email)
  // An old typo doesn't count against today: a quiet 15 minutes (or a lock
  // that has run out) starts the count over.
  const fresh = !entry || now - entry.lastAt > WINDOW_MS || (entry.lockedUntil > 0 && entry.lockedUntil <= now)
  const count = fresh ? 1 : entry.count + 1
  failures.set(email, { count, lastAt: now, lockedUntil: count >= MAX_FAILURES ? now + WINDOW_MS : 0 })
}

export function clearFailures(email: string) {
  failures.delete(email)
}
