import { cookies } from 'next/headers';
import { v4 as uuidv4 } from 'uuid';
import { getCsrfCookieOptions } from './cookieConfig';

const CSRF_TOKEN_COOKIE = 'csrf_token';
const CSRF_TOKEN_HEADER = 'x-csrf-token';

/**
 * Generate a new CSRF token and set it as a cookie
 */
export function generateCsrfToken(): string {
  const token = uuidv4();

  cookies().set(CSRF_TOKEN_COOKIE, token, getCsrfCookieOptions());

  return token;
}

/**
 * Get the CSRF token from cookies
 */
export function getCsrfToken(): string | undefined {
  return cookies().get(CSRF_TOKEN_COOKIE)?.value;
}

/**
 * Validate CSRF token from request header against cookie
 */
export function validateCsrfToken(headerToken: string | null): boolean {
  if (!headerToken) {
    return false;
  }

  const cookieToken = getCsrfToken();

  if (!cookieToken) {
    return false;
  }

  // Constant-time comparison to prevent timing attacks
  return cookieToken === headerToken;
}

/**
 * CSRF Protection middleware for API routes
 */
export function csrfProtection(request: Request): { valid: boolean; error?: string } {
  const method = request.method;

  // Only protect state-changing methods
  if (['GET', 'HEAD', 'OPTIONS'].includes(method)) {
    return { valid: true };
  }

  const headerToken = request.headers.get(CSRF_TOKEN_HEADER);

  if (!validateCsrfToken(headerToken)) {
    return {
      valid: false,
      error: 'Invalid or missing CSRF token'
    };
  }

  return { valid: true };
}

/**
 * Get CSRF token for client-side use
 * This should be called from a GET endpoint
 */
export function getOrCreateCsrfToken(): string {
  let token = getCsrfToken();

  if (!token) {
    token = generateCsrfToken();
  }

  return token;
}
