/**
 * Timeout utility for wrapping external service calls.
 * Provides consistent timeout behavior with proper error classification.
 */

import { ServiceTimeoutError } from './errors'

/**
 * Wraps a Promise with a timeout. If the Promise doesn't resolve within
 * the specified time, throws a ServiceTimeoutError.
 *
 * @param promise - The Promise to wrap
 * @param timeoutMs - Timeout in milliseconds
 * @param service - Service name for error context (e.g., 'WorkOS', 'OpenAI')
 * @param operation - Optional operation name for error context (e.g., 'jwt_verify')
 * @returns The resolved value of the Promise
 * @throws ServiceTimeoutError if the timeout is exceeded
 *
 * @example
 * ```typescript
 * const user = await withTimeout(
 *   workos.userManagement.getUser(userId),
 *   SERVICE_TIMEOUTS.WORKOS_USER,
 *   'WorkOS',
 *   'user_lookup'
 * )
 * ```
 */
export async function withTimeout<T>(
  promise: Promise<T>,
  timeoutMs: number,
  service: string,
  operation?: string
): Promise<T> {
  let timeoutId: ReturnType<typeof setTimeout>

  const timeoutPromise = new Promise<never>((_, reject) => {
    timeoutId = setTimeout(() => {
      reject(new ServiceTimeoutError(service, timeoutMs, operation))
    }, timeoutMs)
  })

  try {
    return await Promise.race([promise, timeoutPromise])
  } finally {
    clearTimeout(timeoutId!)
  }
}

/**
 * Standard timeout values for different service operations.
 * These values are tuned for typical service behavior and cold start scenarios.
 */
export const SERVICE_TIMEOUTS = {
  /** WorkOS JWT verification - allows for cold starts */
  WORKOS_JWT: 15_000,
  /** WorkOS user lookup */
  WORKOS_USER: 10_000,
  /** Simple database queries */
  DATABASE_SIMPLE: 10_000,
  /** Complex database queries (JOINs, aggregations) */
  DATABASE_COMPLEX: 30_000
} as const
