/**
 * Authentication Helper Functions
 * 
 * Utilities for extracting user information from requests,
 * handling JWTs, and generating rate limit keys.
 */

import { createClient } from 'jsr:@supabase/supabase-js@2';

/**
 * Extract user ID from Authorization header JWT
 * Returns null if not authenticated or invalid token
 */
export function extractUserIdFromAuth(req: Request): string | null {
  try {
    const authHeader = req.headers.get('Authorization');
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return null;
    }

    const token = authHeader.substring(7);
    
    // Decode JWT (just the payload, no verification needed for ID extraction)
    const parts = token.split('.');
    if (parts.length !== 3) {
      return null;
    }

    const payload = JSON.parse(atob(parts[1]));
    return payload.sub || null;
  } catch (error) {
    console.error('Error extracting user ID from auth:', error);
    return null;
  }
}

/**
 * Get client IP address from request
 * Handles various proxy headers
 */
export function getClientIP(req: Request): string {
  // Check common proxy headers in order of preference
  const forwardedFor = req.headers.get('x-forwarded-for');
  if (forwardedFor) {
    // x-forwarded-for can contain multiple IPs, take the first one
    return forwardedFor.split(',')[0].trim();
  }

  const realIP = req.headers.get('x-real-ip');
  if (realIP) {
    return realIP.trim();
  }

  const cfConnectingIP = req.headers.get('cf-connecting-ip');
  if (cfConnectingIP) {
    return cfConnectingIP.trim();
  }

  // Fallback to a default value
  return 'unknown';
}

/**
 * Generate a rate limit key for the request
 * Prefers user ID, falls back to IP
 */
export function getRateLimitKey(req: Request, prefix: string = 'user'): string {
  const userId = extractUserIdFromAuth(req);
  if (userId) {
    return `${prefix}:${userId}`;
  }
  
  const clientIP = getClientIP(req);
  return `${prefix}:ip:${clientIP}`;
}

/**
 * Verify JWT token and get user ID using Supabase client
 * More robust than manual decoding, verifies signature
 */
export async function verifyAuthAndGetUserId(
  req: Request,
  supabaseUrl: string,
  supabaseServiceKey: string
): Promise<string | null> {
  try {
    const authHeader = req.headers.get('Authorization');
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return null;
    }

    const token = authHeader.substring(7);
    
    // Create a Supabase client for verification
    const supabase = createClient(supabaseUrl, supabaseServiceKey);
    
    // Verify the JWT
    const { data: { user }, error } = await supabase.auth.getUser(token);
    
    if (error || !user) {
      return null;
    }

    return user.id;
  } catch (error) {
    console.error('Error verifying auth token:', error);
    return null;
  }
}

/**
 * Check if request has valid authentication
 */
export function hasValidAuth(req: Request): boolean {
  const authHeader = req.headers.get('Authorization');
  return authHeader !== null && authHeader.startsWith('Bearer ');
}

/**
 * Extract request metadata for logging
 */
export interface RequestMetadata {
  userId: string | null;
  clientIP: string;
  userAgent: string | null;
  referer: string | null;
  method: string;
  path: string;
}

export function extractRequestMetadata(req: Request): RequestMetadata {
  const url = new URL(req.url);
  
  return {
    userId: extractUserIdFromAuth(req),
    clientIP: getClientIP(req),
    userAgent: req.headers.get('user-agent'),
    referer: req.headers.get('referer'),
    method: req.method,
    path: url.pathname,
  };
}
