import { Request, Response, NextFunction } from "express";
import { validateToken } from "../utils/csrfTokenManager";

/**
 * CSRF protection using token validation
 *
 * This middleware validates the CSRF token sent in the X-CSRF-Token header
 * against the token stored for the authenticated user.
 *
 * Security features:
 * - Validates actual token values (not just presence)
 * - Tokens are user-specific and session-bound
 * - Cryptographically secure token generation
 * - Constant-time comparison to prevent timing attacks
 * - Automatic token expiration (1 hour)
 *
 * The client must:
 * 1. Call GET /api/csrf-token after login to obtain a token
 * 2. Include the token in X-CSRF-Token header for all POST/PUT/DELETE requests
 *
 * Fallback: Also accepts X-Requested-With header for backward compatibility
 */
export const csrfProtection = (req: Request, res: Response, next: NextFunction) => {
    // Skip CSRF check for GET, HEAD, OPTIONS (safe methods)
    if (['GET', 'HEAD', 'OPTIONS'].includes(req.method)) {
        return next();
    }

    const xRequestedWith = req.get('X-Requested-With');
    const xCsrfToken = req.get('X-CSRF-Token');

    // Backward compatibility: Allow X-Requested-With header
    if (xRequestedWith) {
        return next();
    }

    // Check if X-CSRF-Token header is provided
    if (!xCsrfToken) {
        return res.status(403).json({
            success: false,
            message: 'CSRF token is required. Include X-CSRF-Token header with a valid token obtained from GET /api/csrf-token',
        });
    }

    // User must be authenticated for token validation
    const user = (req as any).user;
    if (!user?.id) {
        return res.status(401).json({
            success: false,
            message: 'Authentication required for CSRF validation',
        });
    }

    // Validate the token
    const isValid = validateToken(user.id.toString(), xCsrfToken);

    if (!isValid) {
        return res.status(403).json({
            success: false,
            message: 'CSRF token validation failed. Token may be invalid, expired, or revoked. Please obtain a new token from GET /api/csrf-token',
        });
    }

    // Token is valid, proceed
    next();
};

/**
 * Strict CSRF protection for critical endpoints (financial transactions)
 *
 * This middleware enforces strict CSRF token validation without any fallback options.
 * It REQUIRES a valid X-CSRF-Token header with proper token validation.
 *
 * Use this for sensitive operations like:
 * - Money transfers
 * - Withdrawals
 * - Deposits
 * - Investments
 * - Payment processing
 *
 * NO backward compatibility - X-CSRF-Token with valid token is mandatory.
 */
export const strictCsrfProtection = (req: Request, res: Response, next: NextFunction) => {
    // Skip CSRF check for GET, HEAD, OPTIONS (safe methods)
    if (['GET', 'HEAD', 'OPTIONS'].includes(req.method)) {
        return next();
    }

    const xCsrfToken = req.get('X-CSRF-Token');

    // Check if X-CSRF-Token header is provided
    if (!xCsrfToken) {
        return res.status(403).json({
            success: false,
            message: 'CSRF token is required for this financial operation. Include X-CSRF-Token header with a valid token obtained from GET /api/csrf-token',
        });
    }

    // User must be authenticated for token validation
    const user = (req as any).user;
    if (!user?.id) {
        return res.status(401).json({
            success: false,
            message: 'Authentication required for CSRF validation',
        });
    }

    // Validate the token
    const isValid = validateToken(user.id.toString(), xCsrfToken);

    if (!isValid) {
        return res.status(403).json({
            success: false,
            message: 'CSRF token validation failed for financial operation. Token may be invalid, expired, or revoked. Please obtain a new token from GET /api/csrf-token',
        });
    }

    // Token is valid, proceed
    next();
};
