import { NextFunction, Request, RequestHandler } from 'express';
import { BadRequestError, ErrorCodes } from '../../business/errors';
import { HumandResponse } from '../types/response';
import { MandatoryComposedCursorPaginableVC, MandatoryCursorPaginableVC } from '../validationClasses/mandatoryCursorPagination';
import { genericValidateParams } from './genericValidateParams';

const validateCursorParams = (
    maxLimit: number,
    originFunction: (req: Request) => MandatoryCursorPaginableVC | MandatoryComposedCursorPaginableVC,
    validationClass: typeof MandatoryCursorPaginableVC | typeof MandatoryComposedCursorPaginableVC,
): ((req: Request, res: HumandResponse, next: NextFunction) => RequestHandler) => {
    return genericValidateParams<MandatoryCursorPaginableVC | MandatoryComposedCursorPaginableVC>(
        originFunction,
        (res, output: MandatoryCursorPaginableVC) => {
            const { cursor, limit } = output;
            if (limit === null || limit === undefined) {
                throw new BadRequestError('Param "limit" must be defined', ErrorCodes.INVALID_DATA);
            }
            const newLimit = Number(output.limit);
            if (newLimit > maxLimit) {
                throw new BadRequestError(`The limit must be an integer between 1 and ${maxLimit}`, ErrorCodes.INVALID_DATA);
            }
            res.locals.requiredCursorPagination = { cursor, limit };
        },
        validationClass,
    ) as () => RequestHandler;
};

export const validateMandatoryCursorPagination = (maxLimit: number): ((req: Request, res: HumandResponse, next: NextFunction) => RequestHandler) =>
    validateCursorParams(maxLimit, (req) => req.query as unknown as MandatoryCursorPaginableVC, MandatoryCursorPaginableVC);

export const validateMandatoryComposedCursorPagination = (
    maxLimit: number,
): ((req: Request, res: HumandResponse, next: NextFunction) => RequestHandler) =>
    validateCursorParams(maxLimit, (req) => req.query as unknown as MandatoryComposedCursorPaginableVC, MandatoryComposedCursorPaginableVC);

export const validateMandatoryCursorPaginationInBody = (
    maxLimit: number,
): ((req: Request, res: HumandResponse, next: NextFunction) => RequestHandler) =>
    validateCursorParams(maxLimit, (req) => req.body as unknown as MandatoryCursorPaginableVC, MandatoryCursorPaginableVC);
