// Auth · Login — the web cookie login flow and its TOTP second step.
//
// Mounted at /api/v1/auth/login by auth/index.js, so the two routes below emit
// POST /auth/login and POST /auth/login/totp. No group gate: this is the
// unauthenticated front door. Both routes carry the shared loginGuards stack —
// the TOTP step is a code-guessing surface too.
//
// The bearer-token equivalents for native clients live in mobile.routes.js, and
// the OAuth/OIDC flow in sso.routes.js. Logout and GET /auth/me are in
// session.router.js.

const express = require('express')
const { body } = require('express-validator')

const { login, loginTotp, HONEYPOT_FIELD } = require('./auth.controller')
const { loginGuards } = require('./loginGuards')
const validate = require('../../../middleware/validate')

const loginRouter = express.Router()

loginRouter.post(
  '/',
  // #swagger.tags = ['Auth']
  // #swagger.summary = 'Log in with username and password'
  // #swagger.description = 'On success sets the httpOnly session cookie. If the account has 2FA enabled, returns { totpRequired, challenge } instead and no cookie is set — complete login at POST /login/totp. Rate limited and behind bot/backoff guards.'
  /* #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/LoginRequest" } } } } */
  /* #swagger.responses[200] = { description: 'Session issued, or TOTP challenge required', content: { "application/json": { schema: { $ref: "#/components/schemas/LoginResponse" } } } } */
  /* #swagger.responses[400] = { description: 'Validation error', content: { "application/json": { schema: { $ref: "#/components/schemas/ValidationError" } } } } */
  /* #swagger.responses[401] = { description: 'Incorrect username or password', content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } } } */
  /* #swagger.responses[429] = { description: 'Too many attempts (rate limited / backoff)', content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } } } */
  ...loginGuards,
  body('username').isString().trim().notEmpty(),
  body('password').isString().notEmpty(),
  // Honeypot must be absent/empty for humans; bots that fill it are caught in
  // the controller. Accept-but-ignore here so a filled value still reaches it.
  body(HONEYPOT_FIELD).optional(),
  validate,
  login,
)

// Second factor: same throttling, since it's a code-guessing surface too.
loginRouter.post(
  '/totp',
  // #swagger.tags = ['Auth']
  // #swagger.summary = 'Complete login with a TOTP or recovery code'
  // #swagger.description = 'Second step for 2FA accounts. Exchange the challenge from /login plus either the current authenticator code OR a single-use recovery code for a session cookie. Set trustDevice to remember this browser and skip TOTP on future logins (30 days); if the trusted-device limit is reached the session is still issued and the response carries { trustLimitReached, devices } so the user can revoke one first.'
  /* #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/TotpLoginRequest" } } } } */
  /* #swagger.responses[200] = { description: 'Session issued (optionally with a trusted-device-limit prompt)', content: { "application/json": { schema: { $ref: "#/components/schemas/LoginResponse" } } } } */
  /* #swagger.responses[400] = { description: 'Validation error', content: { "application/json": { schema: { $ref: "#/components/schemas/ValidationError" } } } } */
  /* #swagger.responses[401] = { description: 'Invalid code or expired challenge', content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } } } */
  /* #swagger.responses[429] = { description: 'Too many attempts (rate limited / backoff)', content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } } } */
  ...loginGuards,
  body('challenge').isString().notEmpty(),
  // Either a TOTP code or a recovery code satisfies the second factor; the
  // controller rejects the request when neither verifies.
  body('code').optional({ values: 'falsy' }).isString().trim().isLength({ min: 6, max: 8 }),
  body('recoveryCode').optional({ values: 'falsy' }).isString().trim().isLength({ min: 8, max: 32 }),
  body('trustDevice').optional().isBoolean(),
  body('deviceName').optional({ values: 'falsy' }).isString().trim().isLength({ max: 100 }),
  validate,
  loginTotp,
)

module.exports = loginRouter
