import { Request, Response, NextFunction } from 'express';
import { validationResult } from 'express-validator';
import { sendErrorResponse } from '../utills/response';

/**
 * Middleware to handle validation errors
 * Formats errors to match existing API response format
 */
export const handleValidationErrors = (
    req: Request,
    res: Response,
    next: NextFunction
): void => {
    const errors = validationResult(req);

    if (!errors.isEmpty()) {
        const formattedErrors = errors.array().map(error => ({
            field: error.type === 'field' ? error.path : 'unknown',
            message: error.msg
        }));

        sendErrorResponse(res, 400, 'Validation failed', formattedErrors);
        return;
    }

    next();
};

/**
 * Middleware to strictly validate request body
 * Rejects requests with unknown/unexpected fields
 */
export const strictBodyValidation = (allowedFields: string[]) => {
    return (req: Request, res: Response, next: NextFunction): void => {
        const bodyKeys = Object.keys(req.body);
        const unknownFields = bodyKeys.filter(key => !allowedFields.includes(key));

        if (unknownFields.length > 0) {
            sendErrorResponse(
                res,
                400,
                'Validation failed',
                unknownFields.map(field => ({
                    field,
                    message: 'Unknown field not allowed'
                }))
            );
            return;
        }

        next();
    };
};

/**
 * Password strength requirements
 */
export const passwordRequirements = {
    minLength: 8,
    errorMessage: 'Password must be at least 8 characters long and contain letters and numbers'
};

/**
 * Custom validator for password strength
 */
export const isStrongPassword = (value: string): boolean => {
    if (!value || value.length < passwordRequirements.minLength) {
        return false;
    }

    // Check for at least one letter and one number
    const hasLetter = /[a-zA-Z]/.test(value);
    const hasNumber = /\d/.test(value);

    return hasLetter && hasNumber;
};

/**
 * Custom validator for positive numbers
 */
export const isPositiveNumber = (value: any): boolean => {
    const num = Number(value);
    return !isNaN(num) && num > 0;
};

/**
 * Custom validator for non-negative numbers
 */
export const isNonNegativeNumber = (value: any): boolean => {
    const num = Number(value);
    return !isNaN(num) && num >= 0;
};
