/**
 * Error handling utilities for type-safe error processing
 */

/**
 * Clerk error structure
 */
interface ClerkError {
  errors?: Array<{
    message: string;
    code?: string;
  }>;
  message?: string;
}

/**
 * Type guard to check if error is a Clerk error
 */
function isClerkError(error: unknown): error is ClerkError {
  return (
    typeof error === "object" &&
    error !== null &&
    ("errors" in error || "message" in error)
  );
}

/**
 * Extract error message from unknown error type
 * Handles Clerk errors, standard Error objects, and unknown types
 *
 * @param error - The caught error
 * @param fallback - Fallback message if no message can be extracted
 * @returns Error message string
 */
export function getErrorMessage(
  error: unknown,
  fallback = "An unknown error occurred",
): string {
  // Handle Clerk errors with nested error array
  if (isClerkError(error)) {
    if (error.errors?.[0]?.message) {
      return error.errors[0].message;
    }
    if (error.message) {
      return error.message;
    }
  }

  // Handle standard Error objects
  if (error instanceof Error) {
    return error.message;
  }

  // Handle string errors
  if (typeof error === "string") {
    return error;
  }

  // Fallback for unknown types
  return fallback;
}

/**
 * Type guard to check if metadata has a gymId
 */
interface MetadataWithGymId {
  gymId: string;
}

function hasGymId(metadata: unknown): metadata is MetadataWithGymId {
  return (
    typeof metadata === "object" &&
    metadata !== null &&
    "gymId" in metadata &&
    typeof (metadata as Record<string, unknown>).gymId === "string"
  );
}

/**
 * Safely extract gymId from Clerk public metadata
 *
 * @param user - Clerk user object
 * @returns gymId string or empty string if not found
 */
export function getGymIdFromUser(user: { publicMetadata?: unknown }): string {
  if (hasGymId(user.publicMetadata)) {
    return user.publicMetadata.gymId;
  }
  return "";
}
