/**
 * DashCaddy Error Handler Middleware
 * Centralizes error handling logic to eliminate duplicate catch blocks
 */

const { AppError } = require('./errors');
const { logError } = require('./error-logger');

/**
 * Async route handler wrapper
 * Automatically catches errors and passes to error middleware
 * Usage: app.get('/route', asyncHandler(async (req, res) => { ... }))
 */
function asyncHandler(fn) {
  return (req, res, next) => {
    Promise.resolve(fn(req, res, next)).catch(next);
  };
}

/**
 * Global error handling middleware
 * MUST be registered after all routes in server.js
 */
function errorMiddleware(err, req, res, next) {
  // Log all errors with request context
  logError(req.path, err, {
    method: req.method,
    ip: req.ip,
    userId: req.user?.id,
    body: req.body
  });

  // Determine if this is an operational error (AppError) or programming error
  const isOperational = err.isOperational || err instanceof AppError;
  
  // Status code
  const statusCode = err.statusCode || 500;
  
  // Error code (DC-XXX format)
  const code = err.code || `DC-${statusCode}`;
  
  // Build response
  const response = {
    success: false,
    error: isOperational ? err.message : 'Internal server error',
    code
  };
  
  // Add optional fields if present
  if (err.requiresTotp) response.requiresTotp = true;
  if (err.retryAfter) response.retryAfter = err.retryAfter;
  if (err.field) response.field = err.field;
  if (err.resource) response.resource = err.resource;
  if (err.details && Object.keys(err.details).length > 0) response.details = err.details;
  
  // Development mode: include stack trace
  if (process.env.NODE_ENV === 'development') {
    response.stack = err.stack;
  }
  
  // Send response
  res.status(statusCode).json(response);
  
  // For non-operational errors, log as fatal
  if (!isOperational) {
    console.error('FATAL: Non-operational error detected', {
      error: err.message,
      stack: err.stack,
      path: req.path
    });
  }
}

/**
 * 404 handler for routes not found
 * Register this before the global error handler
 */
function notFoundHandler(req, res, next) {
  const { NotFoundError } = require('./errors');
  next(new NotFoundError(`Route ${req.method} ${req.path}`));
}

module.exports = {
  asyncHandler,
  errorMiddleware,
  notFoundHandler
};
