/**
 * Frontend Error Handler Utility
 * Provides user-friendly error messages and secure error handling
 * Prevents exposure of technical details to users
 */

/**
 * Extract user-friendly error message from API response
 * 
 * @param {Error} error - Axios error object
 * @param {string} defaultMessage - Default message if error cannot be parsed
 * @returns {string} User-friendly error message
 */
export function getErrorMessage(error, defaultMessage = 'An unexpected error occurred') {
  // Check if error response exists
  if (error?.response?.data) {
    const { data } = error.response;
    
    // Server returned a structured error
    if (data.error) {
      return typeof data.error === 'string' ? data.error : data.error.message || defaultMessage;
    }
    
    // Server returned validation errors array
    if (data.errors && Array.isArray(data.errors)) {
      return data.errors.map(e => e.msg || e.message).join(', ');
    }
    
    // Server returned a message
    if (data.message) {
      return data.message;
    }
  }
  
  // Network error
  if (error?.message === 'Network Error' || error?.code === 'ERR_NETWORK') {
    return 'Network error. Please check your connection and try again.';
  }
  
  // Timeout error
  if (error?.code === 'ECONNABORTED' || error?.message?.includes('timeout')) {
    return 'Request timeout. Please try again.';
  }
  
  // HTTP status-based messages
  if (error?.response?.status) {
    const status = error.response.status;
    
    switch (status) {
      case 400:
        return 'Invalid request. Please check your input.';
      case 401:
        return 'Authentication required. Please log in again.';
      case 403:
        return 'You do not have permission to perform this action.';
      case 404:
        return 'Resource not found.';
      case 409:
        return 'This operation conflicts with existing data.';
      case 422:
        return 'Unable to process your request. Please check your input.';
      case 429:
        return 'Too many requests. Please wait a moment and try again.';
      case 500:
        return 'Server error. Please try again later.';
      case 502:
        return 'Bad gateway. The server is temporarily unavailable.';
      case 503:
        return 'Service temporarily unavailable. Please try again later.';
      case 504:
        return 'Gateway timeout. Please try again.';
      default:
        return defaultMessage;
    }
  }
  
  // Generic error message as fallback
  return error?.message || defaultMessage;
}

/**
 * Check if error is an authentication error
 * 
 * @param {Error} error - Error object
 * @returns {boolean} True if authentication error
 */
export function isAuthError(error) {
  return error?.response?.status === 401 || 
         error?.response?.data?.code === 'UNAUTHORIZED' ||
         error?.response?.data?.code === 'AUTH_ERROR';
}

/**
 * Check if error is a permission error
 * 
 * @param {Error} error - Error object
 * @returns {boolean} True if permission error
 */
export function isPermissionError(error) {
  return error?.response?.status === 403 || 
         error?.response?.data?.code === 'FORBIDDEN' ||
         error?.response?.data?.code === 'PERMISSION_ERROR';
}

/**
 * Check if error is a validation error
 * 
 * @param {Error} error - Error object
 * @returns {boolean} True if validation error
 */
export function isValidationError(error) {
  return error?.response?.status === 400 || 
         error?.response?.status === 422 ||
         error?.response?.data?.code === 'VALIDATION_ERROR';
}

/**
 * Check if error is a network error
 * 
 * @param {Error} error - Error object
 * @returns {boolean} True if network error
 */
export function isNetworkError(error) {
  return error?.message === 'Network Error' || 
         error?.code === 'ERR_NETWORK' ||
         error?.code === 'ECONNABORTED';
}

/**
 * Get error type classification
 * 
 * @param {Error} error - Error object
 * @returns {string} Error type: 'auth', 'permission', 'validation', 'network', 'server', 'unknown'
 */
export function getErrorType(error) {
  if (isAuthError(error)) return 'auth';
  if (isPermissionError(error)) return 'permission';
  if (isValidationError(error)) return 'validation';
  if (isNetworkError(error)) return 'network';
  if (error?.response?.status >= 500) return 'server';
  return 'unknown';
}

/**
 * Get error severity level
 * 
 * @param {Error} error - Error object
 * @returns {string} Severity: 'error', 'warning', 'info'
 */
export function getErrorSeverity(error) {
  const status = error?.response?.status;
  
  if (!status) return 'error';
  
  if (status === 401 || status === 403) return 'warning';
  if (status >= 400 && status < 500) return 'info';
  if (status >= 500) return 'error';
  
  return 'error';
}

/**
 * Format error for display in UI
 * 
 * @param {Error} error - Error object
 * @param {Object} options - Formatting options
 * @returns {Object} Formatted error object
 */
export function formatError(error, options = {}) {
  const {
    defaultMessage = 'An unexpected error occurred',
    includeCode = false,
    includeType = false
  } = options;
  
  const message = getErrorMessage(error, defaultMessage);
  const type = getErrorType(error);
  const severity = getErrorSeverity(error);
  
  const formatted = {
    message,
    severity,
    timestamp: new Date().toISOString()
  };
  
  if (includeCode && error?.response?.data?.code) {
    formatted.code = error.response.data.code;
  }
  
  if (includeType) {
    formatted.type = type;
  }
  
  return formatted;
}

/**
 * Handle error with automatic logging
 * Useful for global error boundary
 * 
 * @param {Error} error - Error object
 * @param {string} context - Context where error occurred
 */
export function handleError(error, context = 'Application') {
  // Log to console in development only
  if (process.env.NODE_ENV !== 'production') {
    console.error(`[${context}]`, error);
  }
  
  // You can add additional error tracking here (e.g., Sentry, LogRocket)
  // trackError(error, { context });
  
  return formatError(error);
}

/**
 * Create error notification object for UI
 * 
 * @param {Error} error - Error object
 * @param {Object} options - Options
 * @returns {Object} Notification object
 */
export function createErrorNotification(error, options = {}) {
  const {
    title = 'Error',
    defaultMessage = 'An unexpected error occurred',
    autoHide = true,
    duration = 5000
  } = options;
  
  const formatted = formatError(error, { defaultMessage });
  
  return {
    title,
    message: formatted.message,
    type: 'error',
    severity: formatted.severity,
    autoHide,
    duration,
    timestamp: formatted.timestamp
  };
}

/**
 * Retry helper for failed requests
 * 
 * @param {Function} fn - Async function to retry
 * @param {Object} options - Retry options
 * @returns {Promise} Result of function
 */
export async function retryRequest(fn, options = {}) {
  const {
    maxRetries = 3,
    retryDelay = 1000,
    shouldRetry = (error) => isNetworkError(error) || error?.response?.status >= 500
  } = options;
  
  let lastError;
  
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      lastError = error;
      
      // Don't retry if error shouldn't be retried
      if (!shouldRetry(error)) {
        throw error;
      }
      
      // Don't wait after last attempt
      if (attempt < maxRetries - 1) {
        await new Promise(resolve => setTimeout(resolve, retryDelay * (attempt + 1)));
      }
    }
  }
  
  throw lastError;
}

export default {
  getErrorMessage,
  isAuthError,
  isPermissionError,
  isValidationError,
  isNetworkError,
  getErrorType,
  getErrorSeverity,
  formatError,
  handleError,
  createErrorNotification,
  retryRequest
};
