/**
 * Client-side CSRF protection utilities
 */

import { logger } from './logger';

const CSRF_HEADER_NAME = 'x-csrf-token';
const CSRF_COOKIE_NAME = 'csrf-token';

/**
 * Get CSRF token from browser cookies
 * 
 * @returns CSRF token value or null if not found
 * 
 * @example
 * const token = getCSRFCookie();
 * if (token) {
 *   // Use token in API requests
 * }
 */
export function getCSRFCookie(): string | null {
  if (typeof document === 'undefined') return null;
  
  const cookies = document.cookie.split(';');
  for (const cookie of cookies) {
    const [name, value] = cookie.trim().split('=');
    if (name === CSRF_COOKIE_NAME) {
      return value;
    }
  }
  return null;
}

/**
 * Fetch a new CSRF token from the server
 * This should be called after authentication to get a fresh token
 * 
 * @returns Promise resolving to CSRF token or null if fetch failed
 * 
 * @example
 * const token = await fetchCSRFToken();
 * if (token) {
 *   // Store or use the new token
 * }
 */
export async function fetchCSRFToken(): Promise<string | null> {
  try {
    const response = await fetch('/api/auth/csrf', {
      method: 'GET',
      credentials: 'include', // Include cookies
    });
    
    if (!response.ok) {
      logger.error('Failed to fetch CSRF token:', response.status);
      return null;
    }
    
    const data = await response.json();
    return data.token || null;
  } catch (error) {
    logger.error('Error fetching CSRF token:', error);
    return null;
  }
}

/**
 * Add CSRF token to fetch options
 * Enhances existing request options with CSRF protection headers
 * 
 * @param options - Existing fetch options to enhance
 * @returns Enhanced fetch options with CSRF token header
 * 
 * @example
 * const response = await fetch('/api/data', withCSRFToken({
 *   method: 'POST',
 *   body: JSON.stringify(data)
 * }));
 */
export function withCSRFToken(options: RequestInit = {}): RequestInit {
  const token = getCSRFCookie();
  
  if (!token) {
    logger.warn('No CSRF token found in cookies');
    return options;
  }
  
  return {
    ...options,
    headers: {
      ...options.headers,
      [CSRF_HEADER_NAME]: token,
    },
  };
}

/**
 * Enhanced fetch with CSRF protection
 * Automatically adds CSRF token to requests. If no token exists in cookies,
 * fetches a fresh one before proceeding.
 * 
 * @param input - URL or Request object
 * @param options - Fetch options
 * @returns Promise resolving to Response
 * 
 * @example
 * const response = await csrfFetch('/api/data', {
 *   method: 'POST',
 *   body: JSON.stringify(data)
 * });
 */
export async function csrfFetch(input: RequestInfo | URL, options?: RequestInit): Promise<Response> {
  // If no CSRF cookie exists, fetch one first
  if (!getCSRFCookie()) {
    await fetchCSRFToken();
  }
  const enhancedOptions = withCSRFToken(options);
  return fetch(input, enhancedOptions);
}

/**
 * Add CSRF token to FormData for multipart/form-data requests
 * Appends the CSRF token as a form field
 * 
 * @param formData - FormData object to enhance
 * @returns The same FormData object with CSRF token added
 * 
 * @example
 * const formData = new FormData();
 * formData.append('file', file);
 * addCSRFTokenToFormData(formData);
 * // formData now includes csrf_token field
 */
export function addCSRFTokenToFormData(formData: FormData): FormData {
  const token = getCSRFCookie();
  
  if (token) {
    formData.append('csrf_token', token);
  } else {
    logger.warn('No CSRF token found in cookies');
  }
  
  return formData;
}

/**
 * Initialize CSRF token after authentication
 * Call this after successful login/signup to get a fresh CSRF token
 * 
 * @returns Promise resolving to true if token was successfully fetched
 * 
 * @example
 * const success = await initializeCSRF();
 * if (success) {
 *   // CSRF token is now available for subsequent requests
 * }
 */
export async function initializeCSRF(): Promise<boolean> {
  const token = await fetchCSRFToken();
  return token !== null;
}