/**
 * Centralized Error Formatter Middleware
 * 
 * Standard error response format:
 * {
 *   "error": "ValidationError",
 *   "message": "Human-readable description",
 *   "field": "optional-field-name",
 *   "code": "machine-readable-code"
 * }
 */

const { ValidationError, formatError } = require('../utils/apiError');

/**
 * Extract field name from various validation error patterns
 */
function extractFieldFromError(message) {
  if (!message) return null;
  
  // Patterns like "field must be ..." or "field is ..."
  const fieldMatch = message.match(/^(\w+)\s+(?:must be|is|are)\s+/i);
  if (fieldMatch) return fieldMatch[1];
  
  // Patterns like "year must be..." or "month must be..."
  const yearMonthMatch = message.match(/^(year|month|due_day|interest_rate|actual_amount|start_year|start_month|end_year|end_month)\s+must\b/i);
  if (yearMonthMatch) return yearMonthMatch[1];
  
  // Patterns like "name is required"
  const requiredMatch = message.match(/^(username|password|name|bill_id|category_id|due_day)\s+(?:is|are)\s+required/i);
  if (requiredMatch) return requiredMatch[1];
  
  return null;
}

/**
 * Convert a plain error message/string into a standardized error object
 */
function standardizeError(message, code = 'VALIDATION_ERROR', fieldOverride = null) {
  const field = fieldOverride || extractFieldFromError(message);
  
  return {
    error: code,
    message: typeof message === 'string' ? message : String(message),
    field: field || null,
    code: code
  };
}

/**
 * Express middleware that ensures all error responses follow standard format
 */
function errorFormatter(req, res, next) {
  const originalJson = res.json;
  
  res.json = function(data) {
    // If data is an error object (has error property), standardize it
    if (data && typeof data === 'object' && !Array.isArray(data) && data.error && !data.success) {
      // Already standardized (machine-readable code + human message) — pass through
      if (typeof data.code === 'string' && data.code && typeof data.message === 'string') {
        return originalJson.call(this, data);
      }
      // Use the human text as the message, never as the machine code
      const message = (typeof data.message === 'string' && data.message) ? data.message : data.error;
      const code = (typeof data.code === 'string' && data.code) ? data.code : 'ERROR';
      const standardized = standardizeError(message, code, data.field);
      return originalJson.call(this, standardized);
    }
    return originalJson.call(this, data);
  };
  
  next();
}

/**
 * Helper to format validation errors with proper field extraction
 */
function formatValidationError(message, field) {
  return standardizeError(message, 'VALIDATION_ERROR', field);
}

/**
 * Helper to format not found errors
 */
function formatNotFoundError(message, field) {
  return standardizeError(message, 'NOT_FOUND', field);
}

/**
 * Helper to format authentication errors
 */
function formatAuthError(message) {
  return standardizeError(message, 'AUTH_ERROR');
}

/**
 * Helper to format forbidden/access errors
 */
function formatForbiddenError(message) {
  return standardizeError(message, 'FORBIDDEN');
}

module.exports = {
  errorFormatter,
  standardizeError,
  formatValidationError,
  formatNotFoundError,
  formatAuthError,
  formatForbiddenError,
  extractFieldFromError,
};
