/**
 * Service Error Handler
 * FE-API-013: Standardized error handling for API services
 *
 * Provides a consistent way to handle errors in API services with
 * proper error parsing, user-friendly messages, and context awareness.
 */

import { AxiosError } from 'axios';
import { parseApiError, getValidationErrors } from './apiErrorHandler';
import { formatUserFriendlyError } from './errorMessages';
import type { ApiError } from '@/schemas/apiSchemas';

/**
 * Options for error handling
 */
export interface ErrorHandlerOptions {
  /** Context for context-specific error messages */
  context?:
    | 'auth'
    | 'upload'
    | 'playlist'
    | 'track'
    | 'conversation'
    | 'search';
  /** Whether to include validation details in error messages */
  includeDetails?: boolean;
  /** Custom error message overrides */
  customMessages?: Record<number, string>;
  /** Whether to throw the error or return it */
  throwError?: boolean;
}

/**
 * Standard error handler for API services
 * @param error Unknown error from API call
 * @param options Error handling options
 * @returns Formatted error message or throws ApiError
 */
export function handleServiceError(
  error: unknown,
  options: ErrorHandlerOptions = {},
): string {
  const {
    context,
    includeDetails = false,
    customMessages = {},
    throwError = true,
  } = options;

  // Parse error to ApiError format
  const apiError = parseApiError(error);

  // Check for custom message override
  const status = typeof apiError.code === 'number' ? apiError.code : 0;
  if (status in customMessages) {
    const customMessage = customMessages[status];
    if (throwError) {
      throw new Error(customMessage);
    }
    return customMessage;
  }

  // Format user-friendly message
  const userMessage = formatUserFriendlyError(
    apiError,
    context,
    includeDetails,
  );

  if (throwError) {
    // Create a new Error with the user-friendly message
    // but preserve the ApiError structure for debugging
    const errorWithContext = new Error(userMessage) as Error & {
      apiError?: ApiError;
    };
    errorWithContext.apiError = apiError;
    throw errorWithContext;
  }

  return userMessage;
}

/**
 * Wrapper for API service functions with standardized error handling
 * @param apiCall Async function that makes an API call
 * @param options Error handling options
 * @returns Result of the API call
 * @throws Error with user-friendly message
 */
export async function withErrorHandling<T>(
  apiCall: () => Promise<T>,
  options: ErrorHandlerOptions = {},
): Promise<T> {
  try {
    return await apiCall();
  } catch (error) {
    handleServiceError(error, options);
    // This should never be reached due to throwError default, but TypeScript needs it
    throw error;
  }
}

/**
 * Gets validation errors from an API error
 * @param error Unknown error from API call
 * @returns Record of field -> error message
 */
export function getServiceValidationErrors(
  error: unknown,
): Record<string, string> {
  const apiError = parseApiError(error);
  return getValidationErrors(apiError);
}

/**
 * Checks if an error is a specific HTTP status
 * @param error Unknown error
 * @param status HTTP status code to check
 * @returns True if error matches the status
 */
export function isErrorStatus(error: unknown, status: number): boolean {
  const apiError = parseApiError(error);
  const errorStatus = typeof apiError.code === 'number' ? apiError.code : 0;
  return errorStatus === status;
}

/**
 * Checks if an error is a network error
 * @param error Unknown error
 * @returns True if it's a network error
 */
export function isNetworkError(error: unknown): boolean {
  if (error instanceof AxiosError) {
    return !error.response && !!error.request;
  }

  const apiError = parseApiError(error);
  const code = typeof apiError.code === 'number' ? apiError.code : 0;
  return code === 0 || code === 502 || code === 503;
}

/**
 * Gets a user-friendly error message for display in UI
 * @param error Unknown error
 * @param context Optional context for context-specific messages
 * @returns User-friendly error message
 */
export function getUserFriendlyMessage(
  error: unknown,
  context?: ErrorHandlerOptions['context'],
): string {
  const apiError = parseApiError(error);
  return formatUserFriendlyError(apiError, context);
}

/**
 * Error handler specifically for API service methods
 * Provides consistent error handling pattern for all service functions
 *
 * Usage:
 * ```typescript
 * export async function getSomething(id: string): Promise<Something> {
 *   try {
 *     const response = await apiClient.get(`/something/${id}`);
 *     return response.data;
 *   } catch (error) {
 *     return handleApiServiceError(error, {
 *       context: 'track',
 *       customMessages: {
 *         404: 'Le morceau est introuvable',
 *       },
 *     });
 *   }
 * }
 * ```
 */
export function handleApiServiceError(
  error: unknown,
  options: ErrorHandlerOptions = {},
): never {
  return handleServiceError(error, { ...options, throwError: true }) as never;
}
