// Self-service password resets. A user asks for a reset by email; a tokened link
// is emailed to every active account on that address. Opening the link and choosing
// a new password rotates the hash and revokes every session. The opaque token lives
// only in the emailed link — the DB stores just its sha256 hash (like user_invites
// and mobile refresh tokens), so a DB read never yields a usable reset link. Tokens
// are single-use and short-lived.

const crypto = require('crypto')
const db = require('./passwordResets.db')

// Short by design: a recovery link is a live credential-reset capability, so it
// should not linger the way a 7-day invite does.
const DEFAULT_TTL_MINUTES = 60

function hashToken(raw) {
  return crypto.createHash('sha256').update(String(raw)).digest('hex')
}

// Create a reset for a specific user. Returns { id, token } — the plaintext token
// is returned ONCE (for the email link) and never stored or recoverable afterwards.
async function create({ userId, requestedIp, ttlMinutes = DEFAULT_TTL_MINUTES }) {
  const token = crypto.randomBytes(32).toString('base64url')
  const expiresAt = new Date(Date.now() + ttlMinutes * 60 * 1000)
  const id = await db.insert({ tokenHash: hashToken(token), userId, requestedIp, expiresAt })
  return { id, token }
}

// Resolve a pending, unexpired reset from its plaintext token, else null. Returns
// the RAW row (incl. user_id) for the confirm flow.
async function findValidByToken(token) {
  if (!token) return null
  const row = await db.findByTokenHash(hashToken(token))
  if (!row || row.status !== 'pending') return null
  if (new Date(row.expires_at).getTime() < Date.now()) return null
  return row
}

// Atomically consume a pending reset (double-use-safe). Returns true if this call
// won the race and marked the token used.
async function consume(id) {
  return (await db.markUsed(id)) === 1
}

// Retire any other pending links for this user after a successful reset.
const invalidatePendingForUser = (userId) => db.invalidatePendingForUser(userId)

module.exports = { create, findValidByToken, consume, invalidatePendingForUser, hashToken, DEFAULT_TTL_MINUTES }
