/**
 * ReturnToSanitizer - Sanitizes returnTo URLs to prevent open redirects
 * 
 * Security Rules:
 * - Must start with '/'
 * - Strip protocol and host from absolute URLs
 * - Block /api/* routes
 * - Block /_next/* routes (Next.js internals)
 * - Block paths with file extensions
 * - Return fallback for invalid inputs
 */
export class ReturnToSanitizer {
  /**
   * Sanitizes a returnTo URL to ensure it's safe for redirection
   * 
   * @param input - The raw returnTo value (can be null, undefined, or string)
   * @param fallbackPathname - Fallback path if input is invalid
   * @returns Sanitized path safe for redirection
   */
  sanitizeReturnTo(
    input: string | null | undefined,
    fallbackPathname: string
  ): string {
    // Handle null/undefined/empty
    if (!input || input.trim() === '') {
      return fallbackPathname;
    }

    let path = input.trim();

    // Strip protocol and host from absolute URLs
    // Matches: https://example.com/path, http://localhost:3000/path
    if (path.match(/^https?:\/\//)) {
      try {
        const url = new URL(path);
        path = url.pathname + url.search;
      } catch {
        // Invalid URL format
        return fallbackPathname;
      }
    }

    // Must start with /
    if (!path.startsWith('/')) {
      return fallbackPathname;
    }

    // Block API routes
    if (path.startsWith('/api/')) {
      return fallbackPathname;
    }

    // Block Next.js internal routes
    if (path.startsWith('/_next/')) {
      return fallbackPathname;
    }

    // Block paths with file extensions
    // Check for common file extensions at the end or before query string
    // Excludes version numbers (v1.0) and usernames (john.doe) but catches .pdf, .jpg, .tar.gz, .backup, etc.
    const fileExtensionPattern = /\.(pdf|jpg|jpeg|png|gif|webp|ico|css|js|json|xml|txt|csv|tar|gz|zip|mp4|webm|mov|avi|mp3|wav|svg|bmp|tiff|woff|woff2|ttf|eot|backup|bak|sql|db|exe|dmg|iso|rar|7z)($|\?)/i;
    if (fileExtensionPattern.test(path)) {
      return fallbackPathname;
    }

    // Valid path
    return path;
  }
}
