const { query } = require('../../utils/db')

// SQL for the recovery_codes table. Each row is one bcrypt-hashed, single-use
// backup code. The raw codes are shown to the user exactly once at generation and
// never stored in the clear.

// Bulk-insert freshly generated code hashes for a user. `hashes` is an array of
// bcrypt strings. One multi-row INSERT keeps generation atomic-ish and cheap.
async function insertMany(userId, hashes) {
  if (!hashes || hashes.length === 0) return 0
  const values = hashes.map(() => '(?, ?)').join(', ')
  const params = []
  for (const h of hashes) params.push(userId, h)
  const res = await query(
    `INSERT INTO recovery_codes (user_id, code_hash) VALUES ${values}`,
    params,
  )
  return Number(res.affectedRows || 0)
}

// All not-yet-used codes for a user (hashes included — this is the verify path,
// server-side only). Ordered by id so verification is deterministic.
async function listUnusedForUser(userId) {
  return query(
    'SELECT id, code_hash FROM recovery_codes WHERE user_id = ? AND used_at IS NULL ORDER BY id',
    [userId],
  )
}

// Count a user's remaining (unused) codes — for the status endpoint (never the
// codes themselves).
async function countUnusedForUser(userId) {
  const rows = await query(
    'SELECT COUNT(*) AS n FROM recovery_codes WHERE user_id = ? AND used_at IS NULL',
    [userId],
  )
  return Number(rows[0]?.n || 0)
}

// Mark one code row used (single-use). Guarded on used_at IS NULL so a race can
// only consume it once. Returns rows changed.
async function markUsed(id) {
  const res = await query(
    'UPDATE recovery_codes SET used_at = NOW() WHERE id = ? AND used_at IS NULL',
    [id],
  )
  return Number(res.affectedRows || 0)
}

// Delete every code for a user. Used both when regenerating (replace the set) and
// on TOTP disable / password change/reset. Returns rows removed.
async function deleteAllForUser(userId) {
  const res = await query('DELETE FROM recovery_codes WHERE user_id = ?', [userId])
  return Number(res.affectedRows || 0)
}

module.exports = {
  insertMany,
  listUnusedForUser,
  countUnusedForUser,
  markUsed,
  deleteAllForUser,
}
