/**
 * Pluggable auth routes — DC-046.
 *
 * Mount: /api/v1/auth (under the existing apiRouter prefix).
 *
 * Endpoints:
 *   GET  /login/methods       — list enabled providers + their login methods
 *                               (no secrets). Drives the login UI button list.
 *
 *   POST /login/:provider/initiate  — start the auth flow for `provider`
 *                                     using its default method. The :provider
 *                                     segment maps to a registered AuthProvider
 *                                     (see src/auth/providers/index.js).
 *
 *   POST /login/:provider/verify   — complete the auth flow. Sets the
 *                                     DashCaddy session cookie on success.
 *
 *   GET  /login/recovery-info      — generic lockout-info UI (delegates to
 *                                     the first enabled provider's
 *                                     recoveryInfo(); falls back to a static
 *                                     "no providers enabled" message).
 *
 *   POST /disable/:provider        — turn off a provider (e.g. /api/v1/auth/disable/totp).
 *                                     Provider may require re-verification.
 *
 * The legacy /api/v1/totp/* endpoints (mount: src/app.js → authRoutes →
 * routes/auth/totp.js) are kept as thin pass-throughs to the TOTP provider
 * so old frontends keep working. New frontends should use this namespace.
 */

const express = require('express');
const { ValidationError, NotFoundError } = require('../../src/utilities/errors');
const { ok } = require('../../src/utils/responses');

/**
 * Factory — wires the registry into the router.
 *
 * @param {Object} deps
 * @param {Object} deps.registry  createAuthProviderRegistry() result
 * @param {Function} deps.asyncHandler
 * @param {Function} deps.errorResponse
 * @param {Object} deps.log
 * @returns {express.Router}
 */
module.exports = function({ registry, asyncHandler, errorResponse, log }) {
  const router = express.Router();

  // List all enabled providers + their login methods.
  router.get('/login/methods', asyncHandler(async (_req, res) => {
    const enabled = await registry.listEnabled();
    ok(res, { providers: enabled });
  }, 'auth-methods-list'));

  // Initiate a provider's auth flow. The :provider segment selects which
  // AuthProvider from the registry. methodId is optional — providers may
  // pick their default method if omitted (TOTP does this).
  router.post('/login/:provider/initiate', asyncHandler(async (req, res) => {
    const provider = registry.getProvider(req.params.provider);
    if (!provider) throw new NotFoundError(`Unknown auth provider: ${req.params.provider}`);

    const methodId = req.body?.methodId || (await provider.listMethods())[0]?.id;
    if (!methodId) throw new ValidationError('No methodId provided and provider has no methods', 'methodId');

    if (!(await provider.isEnabled())) {
      throw new ValidationError(`Provider ${req.params.provider} is not enabled`, 'provider');
    }

    log.debug('auth', 'provider initiate', { provider: req.params.provider, methodId });
    return provider.initiate(methodId, req, res);
  }, 'auth-initiate'));

  // Verify a provider's auth flow. On success the provider creates the
  // DashCaddy session cookie (same cookie across all providers).
  router.post('/login/:provider/verify', asyncHandler(async (req, res) => {
    const provider = registry.getProvider(req.params.provider);
    if (!provider) throw new NotFoundError(`Unknown auth provider: ${req.params.provider}`);

    const methodId = req.body?.methodId || (await provider.listMethods())[0]?.id;
    if (!methodId) throw new ValidationError('No methodId provided and provider has no methods', 'methodId');

    log.debug('auth', 'provider verify', { provider: req.params.provider, methodId });
    return provider.verify(methodId, req, res);
  }, 'auth-verify'));

  // Generic lockout-recovery info. Today this delegates to TOTP (the only
  // provider). When email magic link lands, it can return its own recovery
  // shape and the UI will switch.
  router.get('/login/recovery-info', asyncHandler(async (_req, res) => {
    const totp = registry.getProvider('totp');
    if (totp) {
      const info = await totp.recoveryInfo();
      return ok(res, info);
    }
    ok(res, {
      status: 'not_configured',
      isSetUp: false,
      hint: 'No auth providers are configured on this server yet.',
    });
  }, 'auth-recovery-info'));

  // Disable a provider.
  router.post('/disable/:provider', asyncHandler(async (req, res) => {
    const provider = registry.getProvider(req.params.provider);
    if (!provider) throw new NotFoundError(`Unknown auth provider: ${req.params.provider}`);
    log.info('auth', 'provider disable', { provider: req.params.provider });
    return provider.disable(req, res);
  }, 'auth-disable'));

  return router;
};