const { body, param, query, validationResult } = require('express-validator');

const handleValidationErrors = (req, res, next) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({
      error: 'Validation failed',
      details: errors.array().map(err => ({
        field: err.path,
        message: err.msg,
        value: err.value,
      })),
    });
  }
  next();
};

const validators = {
  uuid: (field, location = 'param') => {
    const validator = location === 'param' ? param(field) : body(field);
    return validator.isUUID().withMessage(`${field} must be a valid UUID`);
  },

  requiredString: (field, min = 1, max = 255) =>
    body(field)
      .trim()
      .notEmpty().withMessage(`${field} is required`)
      .isLength({ min, max }).withMessage(`${field} must be ${min}-${max} characters`),

  optionalString: (field, max = 255) =>
    body(field)
      .optional()
      .trim()
      .isLength({ max }).withMessage(`${field} must be at most ${max} characters`),

  slug: (field) =>
    body(field)
      .optional()
      .trim()
      .matches(/^[a-z0-9_-]+$/i).withMessage(`${field} can only contain letters, numbers, dashes, underscores`),

  email: (field) =>
    body(field)
      .trim()
      .isEmail().withMessage('Must be a valid email')
      .normalizeEmail(),

  optionalEmail: (field) =>
    body(field)
      .optional()
      .trim()
      .isEmail().withMessage('Must be a valid email')
      .normalizeEmail(),

  enum: (field, values) =>
    body(field)
      .optional()
      .isIn(values).withMessage(`${field} must be one of: ${values.join(', ')}`),

  boolean: (field) =>
    body(field)
      .optional()
      .isBoolean().withMessage(`${field} must be a boolean`),

  integer: (field, min, max) => {
    let validator = body(field).optional().isInt();
    if (min !== undefined) validator = validator.custom(val => val >= min).withMessage(`${field} must be at least ${min}`);
    if (max !== undefined) validator = validator.custom(val => val <= max).withMessage(`${field} must be at most ${max}`);
    return validator;
  },

  pagination: () => [
    query('page').optional().isInt({ min: 0 }).toInt(),
    query('limit').optional().isInt({ min: 1, max: 100 }).toInt(),
  ],

  url: (field) =>
    body(field)
      .optional()
      .trim()
      .isURL().withMessage(`${field} must be a valid URL`),
};

function createEntityValidation(entityConfig = {}) {
  const { fields = [], requiredFields = [] } = entityConfig;

  const fieldValidators = fields.map(field => {
    if (requiredFields.includes(field.name)) {
      return validators.requiredString(`data.${field.name}`, field.min || 1, field.max || 255);
    }
    return validators.optionalString(`data.${field.name}`, field.max || 255);
  });

  return {
    create: [...fieldValidators, handleValidationErrors],
    update: [validators.uuid('id'), ...fieldValidators, handleValidationErrors],
    delete: [validators.uuid('id'), handleValidationErrors],
    get: [validators.uuid('id'), handleValidationErrors],
    list: [...validators.pagination(), handleValidationErrors],
  };
}

module.exports = { handleValidationErrors, validators, createEntityValidation };
