/**
 * Error Formatting Utility for Edge Functions
 * 
 * Provides robust error message extraction from various error types:
 * - Standard Error objects
 * - Supabase PostgresError objects (plain objects with message/details/code/hint)
 * - Raw objects and primitives
 * 
 * Eliminates "[object Object]" errors by properly extracting error details.
 */

/**
 * Format error objects for logging
 * Handles Error objects, Supabase errors (plain objects), and primitives
 * 
 * @param error - Any error value
 * @returns Formatted, human-readable error message string
 */
export function formatEdgeError(error: unknown): string {
  // Standard Error objects
  if (error instanceof Error) {
    return error.message;
  }
  
  // Object-like errors (Supabase PostgresError, etc.)
  if (typeof error === 'object' && error !== null) {
    const err = error as any;
    
    // Try common error message properties
    if (err.message && typeof err.message === 'string') {
      // Include additional Supabase error details if present
      const parts: string[] = [err.message];
      
      if (err.details && typeof err.details === 'string') {
        parts.push(`Details: ${err.details}`);
      }
      
      if (err.hint && typeof err.hint === 'string') {
        parts.push(`Hint: ${err.hint}`);
      }
      
      if (err.code && typeof err.code === 'string') {
        parts.push(`Code: ${err.code}`);
      }
      
      return parts.join(' | ');
    }
    
    // Some errors nest the actual error in an 'error' property
    if (err.error) {
      return formatEdgeError(err.error);
    }
    
    // Some APIs use 'msg' instead of 'message'
    if (err.msg && typeof err.msg === 'string') {
      return err.msg;
    }
    
    // Last resort: stringify the entire object
    try {
      const stringified = JSON.stringify(error, null, 2);
      return stringified.length > 500 
        ? stringified.substring(0, 500) + '... (truncated)'
        : stringified;
    } catch {
      // JSON.stringify can fail on circular references
      return 'Unknown error (could not stringify)';
    }
  }
  
  // Primitive values (strings, numbers, etc.)
  return String(error);
}

/**
 * Convert any error to a proper Error instance
 * Use this before throwing to ensure proper stack traces
 * 
 * @param error - Any error value
 * @returns Error instance with formatted message
 */
export function toError(error: unknown): Error {
  if (error instanceof Error) {
    return error;
  }
  
  const message = formatEdgeError(error);
  const newError = new Error(message);
  
  // Preserve original error as property for debugging
  (newError as any).originalError = error;
  
  return newError;
}
