/**
 * Resilience utilities for external service calls
 *
 * Provides guard functions that wrap external service operations with:
 * - Error handling
 * - Timeout protection
 * - Graceful fallback values
 * - Bilingual error messages
 *
 * Used by health-checks.ts and whatsapp.service.ts
 */

import { logger } from './logger';

/**
 * Result of a guarded operation
 */
export interface DegradationResult<T> {
  success: boolean;
  data: T;
  fallback: boolean;
  error?: string;
  userMessage: {
    en: string;
    ar: string;
  };
}

/**
 * Context for guard operations
 */
type GuardContext = Record<string, unknown>;

/**
 * Service-specific error messages
 */
const SERVICE_MESSAGES: Record<string, { en: string; ar: string }> = {
  stripe: {
    en: 'Payment service is temporarily unavailable. Please try again later.',
    ar: 'خدمة الدفع غير متاحة مؤقتاً. يرجى المحاولة مرة أخرى لاحقاً.',
  },
  whatsapp: {
    en: 'WhatsApp service is temporarily unavailable. Please try again later.',
    ar: 'خدمة واتساب غير متاحة مؤقتاً. يرجى المحاولة مرة أخرى لاحقاً.',
  },
};

/**
 * Default timeout for external service calls (10 seconds)
 */
const DEFAULT_TIMEOUT_MS = 10000;

/**
 * Execute a guarded operation with error handling and timeout
 */
async function executeGuard<T>(
  serviceName: 'stripe' | 'whatsapp',
  operation: () => Promise<T>,
  fallback: T,
  context?: GuardContext
): Promise<DegradationResult<T>> {
  const operationName = (context?.operationName as string) || serviceName;

  try {
    // Create timeout promise
    const timeoutPromise = new Promise<never>((_, reject) => {
      setTimeout(() => {
        reject(new Error(`Operation timed out after ${DEFAULT_TIMEOUT_MS}ms`));
      }, DEFAULT_TIMEOUT_MS);
    });

    // Race the operation against the timeout
    const data = await Promise.race([operation(), timeoutPromise]);

    return {
      success: true,
      data,
      fallback: false,
      userMessage: {
        en: 'Operation completed successfully.',
        ar: 'تمت العملية بنجاح.',
      },
    };
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : String(error);
    const isTimeout = errorMessage.includes('timed out');

    logger.warn(`${serviceName} guard triggered fallback`, {
      service: serviceName,
      operation: operationName,
      error: errorMessage,
      isTimeout,
      ...context,
    });

    return {
      success: false,
      data: fallback,
      fallback: true,
      error: errorMessage,
      userMessage: SERVICE_MESSAGES[serviceName],
    };
  }
}

/**
 * Guard wrapper for Stripe operations
 *
 * @param operation - Async function to execute
 * @param fallback - Value to return if operation fails
 * @param context - Optional context for logging
 * @returns DegradationResult with success status and data
 */
export async function withStripeGuard<T>(
  operation: () => Promise<T>,
  fallback: T,
  context?: GuardContext
): Promise<DegradationResult<T>> {
  return executeGuard('stripe', operation, fallback, context);
}

/**
 * Guard wrapper for WhatsApp operations
 *
 * @param operation - Async function to execute
 * @param fallback - Value to return if operation fails
 * @param context - Optional context for logging
 * @returns DegradationResult with success status and data
 */
export async function withWhatsAppGuard<T>(
  operation: () => Promise<T>,
  fallback: T,
  context?: GuardContext
): Promise<DegradationResult<T>> {
  return executeGuard('whatsapp', operation, fallback, context);
}
