/**
 * Customers Validation Rules
 * Input validation rules for customer endpoints
 */

// Import express-validator for request validation
const { body, param, query, validationResult } = require('express-validator');
// Import custom validation error class
const { ValidationError } = require('../../../utils/errors');

/**
 * Validation middleware
 * Handles validation errors and formats response
 */
const handleValidationErrors = (req, res, next) => {
  // Get validation errors
  const errors = validationResult(req); // Get validation errors
  
  // Check if there are errors
  if (!errors.isEmpty()) {
    // Extract error messages
    const errorMessages = errors.array().map(error => ({
      field: error.param, // Field name
      message: error.msg, // Error message
    })); // Map errors to messages
    
    // Throw validation error
    throw new ValidationError('Validation failed', errorMessages); // Throw validation error
  }
  
  // Continue to next middleware if no errors
  next(); // Continue
};

/**
 * Validate create customer request
 */
const validateCreateCustomer = [
  // Validate name (required)
  body('name')
    .notEmpty()
    .withMessage('Customer name is required')
    .trim()
    .isLength({ min: 1, max: 150 })
    .withMessage('Customer name must be between 1 and 150 characters'),
  
  // Validate customer_type (optional)
  body('customer_type')
    .optional()
    .isIn(['B2C', 'B2B'])
    .withMessage('Customer type must be either B2C or B2B'),
  
  // Validate email (optional)
  body('email')
    .optional({ checkFalsy: true })
    .trim()
    .isEmail()
    .withMessage('Email must be a valid email address')
    .normalizeEmail()
    .isLength({ max: 255 })
    .withMessage('Email must be at most 255 characters'),
  
  // Validate phone (optional)
  body('phone')
    .optional({ checkFalsy: true })
    .trim()
    .isLength({ max: 20 })
    .withMessage('Phone must be at most 20 characters'),
  
  // Validate kra_pin (optional)
  body('kra_pin')
    .optional({ checkFalsy: true })
    .trim()
    .isLength({ max: 20 })
    .withMessage('KRA PIN must be at most 20 characters'),
  
  // Validate credit_limit (optional)
  body('credit_limit')
    .optional()
    .isFloat({ min: 0 })
    .withMessage('Credit limit must be a non-negative number'),
  
  // Validate price_list_id (optional)
  body('price_list_id')
    .optional()
    .isInt({ min: 1 })
    .withMessage('Price list ID must be a positive integer'),
  
  // Handle validation errors
  handleValidationErrors,
];

/**
 * Validate get customer by ID request
 */
const validateGetCustomer = [
  // Validate id parameter (required)
  param('id')
    .isInt({ min: 1 })
    .withMessage('Customer ID must be a positive integer'),
  
  // Handle validation errors
  handleValidationErrors,
];

/**
 * Validate update customer request
 */
const validateUpdateCustomer = [
  // Validate id parameter (required)
  param('id')
    .isInt({ min: 1 })
    .withMessage('Customer ID must be a positive integer'),
  
  // Validate name (optional)
  body('name')
    .optional()
    .trim()
    .isLength({ min: 1, max: 150 })
    .withMessage('Customer name must be between 1 and 150 characters'),
  
  // Validate customer_type (optional)
  body('customer_type')
    .optional()
    .isIn(['B2C', 'B2B'])
    .withMessage('Customer type must be either B2C or B2B'),
  
  // Validate email (optional)
  body('email')
    .optional({ checkFalsy: true })
    .trim()
    .isEmail()
    .withMessage('Email must be a valid email address')
    .normalizeEmail()
    .isLength({ max: 255 })
    .withMessage('Email must be at most 255 characters'),
  
  // Validate phone (optional)
  body('phone')
    .optional({ checkFalsy: true })
    .trim()
    .isLength({ max: 20 })
    .withMessage('Phone must be at most 20 characters'),
  
  // Validate kra_pin (optional)
  body('kra_pin')
    .optional({ checkFalsy: true })
    .trim()
    .isLength({ max: 20 })
    .withMessage('KRA PIN must be at most 20 characters'),
  
  // Validate credit_limit (optional)
  body('credit_limit')
    .optional()
    .isFloat({ min: 0 })
    .withMessage('Credit limit must be a non-negative number'),
  
  // Validate price_list_id (optional, can be null)
  body('price_list_id')
    .optional()
    .custom((value) => {
      // Allow null or positive integer
      if (value === null || value === undefined) {
        return true; // Null is allowed
      }
      if (typeof value === 'number' && value >= 1) {
        return true; // Positive integer is allowed
      }
      throw new Error('Price list ID must be null or a positive integer'); // Throw error if invalid
    }),
  
  // Validate active (optional)
  body('active')
    .optional()
    .isBoolean()
    .withMessage('Active must be a boolean'),
  
  // Handle validation errors
  handleValidationErrors,
];

/**
 * Validate delete customer request
 */
const validateDeleteCustomer = [
  // Validate id parameter (required)
  param('id')
    .isInt({ min: 1 })
    .withMessage('Customer ID must be a positive integer'),
  
  // Handle validation errors
  handleValidationErrors,
];

/**
 * Validate list customers request
 */
const validateListCustomers = [
  // Validate customer_type query parameter (optional)
  query('customer_type')
    .optional()
    .isIn(['B2C', 'B2B'])
    .withMessage('Customer type must be either B2C or B2B'),
  
  // Validate active query parameter (optional)
  query('active')
    .optional()
    .isIn(['true', 'false'])
    .withMessage('Active must be either true or false'),
  
  // Validate price_list_id query parameter (optional)
  query('price_list_id')
    .optional()
    .isInt({ min: 1 })
    .withMessage('Price list ID must be a positive integer'),
  
  // Validate search query parameter (optional)
  query('search')
    .optional()
    .trim()
    .isLength({ min: 1 })
    .withMessage('Search term must not be empty'),
  
  // Validate page query parameter (optional)
  query('page')
    .optional()
    .isInt({ min: 1 })
    .withMessage('Page must be a positive integer'),
  
  // Validate limit query parameter (optional)
  query('limit')
    .optional()
    .isInt({ min: 1, max: 100 })
    .withMessage('Limit must be between 1 and 100'),
  
  // Handle validation errors
  handleValidationErrors,
];

/**
 * Validate search customers request
 */
const validateSearchCustomers = [
  // Validate q query parameter (required)
  query('q')
    .notEmpty()
    .withMessage('Search term (q) is required')
    .trim()
    .isLength({ min: 1 })
    .withMessage('Search term must not be empty'),
  
  // Validate limit query parameter (optional)
  query('limit')
    .optional()
    .isInt({ min: 1, max: 100 })
    .withMessage('Limit must be between 1 and 100'),
  
  // Handle validation errors
  handleValidationErrors,
];

// Export all validations
module.exports = {
  validateCreateCustomer,
  validateGetCustomer,
  validateUpdateCustomer,
  validateDeleteCustomer,
  validateListCustomers,
  validateSearchCustomers,
};
