// Trusted-device store. Thin logic layer over trustedDevices.db — mirrors the
// mobileSessions model split (.db = SQL, .model = the API the rest of the app
// calls). The opaque trust token lives client-side; only its sha256 hash is
// persisted (hashing is done by the session service so caller + store agree, the
// same seam as mobile refresh tokens).

const db = require('./trustedDevices.db')

// Max active trusted devices per user. Enforced by assertUnderCap (no silent
// pruning — an over-cap trust attempt is refused so the client can prompt the user
// to revoke one first). See docs/website/TRUSTED_DEVICES_MFA.md §5.
const MAX_TRUSTED_DEVICES = Number(process.env.MAX_TRUSTED_DEVICES) || 10

// Persist a newly trusted device (by token hash). Returns the row id.
async function store({ userId, tokenHash, platform, deviceName, deviceHash, userAgent, expiresAt }) {
  return db.insert({ userId, tokenHash, platform, deviceName, deviceHash, userAgent, expiresAt })
}

// Return the stored row for a still-valid (unrevoked, unexpired) trust token, else
// null. Used by the login path to decide whether the TOTP step can be skipped.
async function findValidByHash(tokenHash) {
  return db.findValidByHash(tokenHash)
}

// Stamp last_used_at when a device's trust is honored at login.
async function touchLastUsed(id) {
  return db.touchLastUsed(id)
}

// List a user's active trusted devices (self-service list + admin per-user view).
async function listActiveForUser(userId) {
  return db.listActiveForUser(userId)
}

// True if the user is at/over the trusted-device cap. Callers refuse the insert and
// signal the client to revoke one first, rather than pruning silently.
async function isAtCap(userId) {
  const n = await db.countActiveForUser(userId)
  return n >= MAX_TRUSTED_DEVICES
}

// Revoke one of a user's trusted devices by row id (ownership-scoped). Returns rows
// changed (0 if it wasn't theirs / already gone — treat idempotently).
async function revokeByIdForUser(id, userId) {
  return db.revokeByIdForUser(id, userId)
}

// Revoke all of a user's trusted devices ("untrust everywhere" + the invalidation
// hook on password change/reset / TOTP disable). Returns rows changed.
async function revokeAllForUser(userId) {
  return db.revokeAllForUser(userId)
}

// Drop expired/revoked rows.
async function pruneExpired() {
  return db.pruneExpired()
}

module.exports = {
  MAX_TRUSTED_DEVICES,
  store,
  findValidByHash,
  touchLastUsed,
  listActiveForUser,
  isAtCap,
  revokeByIdForUser,
  revokeAllForUser,
  pruneExpired,
}
