import { toast } from '@/components/ui/use-toast';

// Define the error response structure
interface ApiErrorResponse {
  message?: string;
  errors?: Record<string, string[]>;
  status?: number;
}

// Define HTTP error response structure
interface HttpErrorResponse {
  status: number;
  data: ApiErrorResponse;
}

// Define API error structure
interface ApiError {
  response?: HttpErrorResponse;
  message?: string;
  name?: string;
  code?: string;
}

// Define error messages for specific status codes
const ERROR_MESSAGES = {
  401: 'Authentication failed. Please log in again.',
  403: 'You are not authorized to perform this action.',
  419: 'Your session has expired. Please log in again.',
  422: 'Validation failed. Please check your input.',
  500: 'Server error occurred. Please try again later.',
} as const;

// Define fallback messages for different operations
const FALLBACK_MESSAGES = {
  upload: 'Failed to upload document. Please try again.',
  update: 'Failed to update document. Please try again.',
  delete: 'Failed to delete document. Please try again.',
  fetch: 'Failed to fetch data. Please try again.',
  default: 'An unexpected error occurred. Please try again.',
} as const;

// Type for operation keys
type OperationType = keyof typeof FALLBACK_MESSAGES;

// Type for error status codes
type ErrorStatusCode = keyof typeof ERROR_MESSAGES;

/**
 * Type guard to check if error is an API error
 */
const isApiError = (error: unknown): error is ApiError => {
  return typeof error === 'object' && error !== null && 'response' in error;
};

/**
 * Type guard to check if status is a known error status code
 */
const isKnownErrorStatus = (status: number): status is ErrorStatusCode => {
  return status in ERROR_MESSAGES;
};

/**
 * Extracts a user-friendly error message from API error response
 */
export const extractErrorMessage = (
  error: unknown,
  operation: OperationType = 'default'
): string => {
  // Handle network errors or errors without response
  if (!isApiError(error) || !error.response) {
    return FALLBACK_MESSAGES[operation];
  }

  const { status, data } = error.response;
  const errorData = data as ApiErrorResponse;

  // Handle validation errors (422) with detailed field errors FIRST
  if (status === 422 && errorData?.errors) {
    const fieldErrors = Object.entries(errorData.errors)
      .map(([field, messages]) => {
        const fieldName = field.charAt(0).toUpperCase() + field.slice(1);
        return `${fieldName}: ${messages.join(', ')}`;
      })
      .join('\n');

    return fieldErrors || errorData.message || ERROR_MESSAGES[422];
  }

  // Handle specific status codes with predefined messages
  if (isKnownErrorStatus(status)) {
    return ERROR_MESSAGES[status];
  }

  // Use backend message if available and meaningful
  if (errorData?.message && errorData.message !== 'Validation failed') {
    return errorData.message;
  }

  // Fallback to operation-specific message
  return FALLBACK_MESSAGES[operation];
};

/**
 * Shows a toast notification with the appropriate error message
 */
export const showApiErrorToast = (
  error: unknown,
  operation: OperationType = 'default'
): void => {
  const message = extractErrorMessage(error, operation);

  toast({
    title: 'Error',
    description: message,
    // variant: 'destructive',
  });
};

/**
 * Handles API errors with automatic toast notification
 * Returns the error message for additional handling if needed
 */
export const handleApiError = (
  error: unknown,
  operation: OperationType = 'default',
  showToast: boolean = true
): string => {
  const message = extractErrorMessage(error, operation);

  if (showToast) {
    toast({
      title: 'Error',
      description: message,
      // variant: 'destructive',
    });
  }

  return message;
};

/**
 * Checks if the error is a specific type that requires special handling
 */
export const isAuthenticationError = (error: unknown): boolean => {
  if (!isApiError(error)) return false;
  const status = error.response?.status;
  return status === 401 || status === 419;
};

export const isAuthorizationError = (error: unknown): boolean => {
  if (!isApiError(error)) return false;
  return error.response?.status === 403;
};

export const isValidationError = (error: unknown): boolean => {
  if (!isApiError(error)) return false;
  return error.response?.status === 422;
};

export const isServerError = (error: unknown): boolean => {
  if (!isApiError(error)) return false;
  return error.response?.status === 500;
};

/**
 * Custom hook-like function for handling errors in async operations
 */
export const withErrorHandling = async <T>(
  operation: () => Promise<T>,
  operationType: OperationType = 'default',
  showToast: boolean = true
): Promise<{ data?: T; error?: string }> => {
  try {
    const data = await operation();
    return { data };
  } catch (error: unknown) {
    const errorMessage = handleApiError(error, operationType, showToast);
    return { error: errorMessage };
  }
};