import { Request, Response, NextFunction } from 'express';
import Joi from 'joi';
import httpStatus from 'http-status';
import pick from '@/shared/utils/pick.js';
import ApiError from '@/shared/utils/errors/ApiError.js';

const validate =
  (
    schema: Record<string, unknown> | ((req: Request) => Record<string, unknown>), // supports function-based schema
  ) =>
  (req: Request, _res: Response, next: NextFunction): void => {
    // if schema is function then call it and pass req
    const resolvedSchema = typeof schema === 'function' ? schema(req) : schema;
    const validSchema = pick(resolvedSchema, ['params', 'query', 'body']);
    const object = pick(req, Object.keys(validSchema));

    const { value, error } = Joi.compile(validSchema)
      .prefs({ errors: { label: 'key' } })
      .validate(object);

    if (error) {
      const errorMessage = error.details
        .map((details) => details.message)
        .join(', ');
      return next(new ApiError(httpStatus.BAD_REQUEST, errorMessage));
    }
    Object.assign(req, value);
    return next();
  };

export default validate;
