/**
 * Centralized Error Formatter Middleware
 *
 * Standard error response format:
 * { "error", "message", "field", "code" }
 */

import type { Req, Res, Next } from '../types/http';

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

/** Extract field name from various validation error patterns */
function extractFieldFromError(message: any): string | null {
  if (!message) return null;

  const fieldMatch = message.match(/^(\w+)\s+(?:must be|is|are)\s+/i);
  if (fieldMatch) return fieldMatch[1];

  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];

  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: any, code = 'VALIDATION_ERROR', fieldOverride: any = 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: Req, res: Res, next: Next): void {
  const originalJson = res.json;

  res.json = function (this: any, data: any) {
    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);
      }
      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();
}

function formatValidationError(message: any, field?: any) {
  return standardizeError(message, 'VALIDATION_ERROR', field);
}

function formatNotFoundError(message: any, field?: any) {
  return standardizeError(message, 'NOT_FOUND', field);
}

function formatAuthError(message: any) {
  return standardizeError(message, 'AUTH_ERROR');
}

function formatForbiddenError(message: any) {
  return standardizeError(message, 'FORBIDDEN');
}

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