const express = require('express');
const { ValidationError, ForbiddenError, NotFoundError } = require('../../src/utilities/errors');
const { ok, successMessage } = require('../../src/utils/responses');
/**
 * Auth API keys routes factory
 * @param {Object} deps - Explicit dependencies
 * @param {Object} deps.authManager - Auth manager
 * @param {Function} deps.asyncHandler - Async route handler wrapper
 * @param {Object} deps.log - Logger instance
 * @returns {express.Router}
 */

module.exports = function({ authManager, asyncHandler, log }) {
  const router = express.Router();

  // Helper function to parse expiration strings to milliseconds
  function parseExpiration(expStr) {
    const match = expStr.match(/^(\d+)([smhdy])$/);
    if (!match) return 24 * 60 * 60 * 1000; // default 24h

    const value = parseInt(match[1], 10);
    const unit = match[2];

    const multipliers = {
      s: 1000,
      m: 60 * 1000,
      h: 60 * 60 * 1000,
      d: 24 * 60 * 60 * 1000,
      y: 365 * 24 * 60 * 60 * 1000
    };

    return value * (multipliers[unit] || multipliers.h);
  }

  // List all API keys
  router.get('/auth/keys', asyncHandler(async (req, res) => {
    // Require session authentication (not API key - can't manage keys with key itself)
    if (!req.auth || req.auth.type !== 'session') {
      throw new ForbiddenError('API key management requires TOTP session authentication');
    }

    const keys = await authManager.listAPIKeys();
    ok(res, { keys });
  }, 'auth-keys-list'));

  // Generate new API key
  router.post('/auth/keys', asyncHandler(async (req, res) => {
    // Require session authentication
    if (!req.auth || req.auth.type !== 'session') {
      throw new ForbiddenError('API key generation requires TOTP session authentication');
    }

    const { name, scopes } = req.body;

    if (!name || typeof name !== 'string' || name.trim().length === 0) {
      throw new ValidationError('API key name is required', 'name');
    }

    // Validate scopes if provided
    const validScopes = ['read', 'write', 'admin'];
    if (scopes && (!Array.isArray(scopes) || !scopes.every(s => validScopes.includes(s)))) {
      throw new ValidationError(`Invalid scopes. Valid options: ${validScopes.join(', ')}`, 'scopes');
    }

    const keyData = await authManager.generateAPIKey(
      name.trim(),
      scopes || ['read', 'write']
    );

    ok(res, {
      key: keyData.key,
      id: keyData.id,
      name: keyData.name,
      scopes: keyData.scopes,
      createdAt: keyData.createdAt,
      warning: 'Save this key securely - it will not be shown again'
    });
  }, 'auth-keys-generate'));

  // Revoke API key
  router.delete('/auth/keys/:keyId', asyncHandler(async (req, res) => {
    // Require session authentication
    if (!req.auth || req.auth.type !== 'session') {
      throw new ForbiddenError('API key revocation requires TOTP session authentication');
    }

    const { keyId } = req.params;

    if (!keyId || typeof keyId !== 'string') {
      throw new ValidationError('Key ID is required', 'keyId');
    }

    const success = await authManager.revokeAPIKey(keyId);

    if (success) {
      successMessage(res, 'API key revoked successfully');
    } else {
      throw new NotFoundError(`API key ${keyId}`);
    }
  }, 'auth-keys-revoke'));

  // Generate JWT from TOTP session
  router.post('/auth/jwt', asyncHandler(async (req, res) => {
    // Require session authentication
    if (!req.auth || req.auth.type !== 'session') {
      throw new ForbiddenError('JWT generation requires TOTP session authentication');
    }

    const { expiresIn, userId } = req.body;

    // Validate expiresIn format if provided (e.g., '24h', '7d', '1y')
    const validExpiresIn = /^(\d+[smhdy])$/.test(expiresIn || '24h');
    if (expiresIn && !validExpiresIn) {
      throw new ValidationError('Invalid expiresIn format. Use: 60s, 15m, 24h, 7d, 1y', 'expiresIn');
    }

    const token = await authManager.generateJWT(
      {
        sub: userId || 'dashcaddy-admin',
        scope: ['admin'] // Session-generated JWTs have admin scope
      },
      expiresIn || '24h'
    );

    // Calculate expiration timestamp
    const expiresInMs = parseExpiration(expiresIn || '24h');
    const expiresAt = new Date(Date.now() + expiresInMs).toISOString();

    ok(res, {
      token,
      expiresAt,
      usage: 'Include in Authorization header as: Bearer <token>'
    });
  }, 'auth-jwt-generate'));

  return router;
};
