/**
 * Pricing Validations
 * Validation rules for pricing operations
 */

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

/**
 * Validation middleware
 * Checks validation results and throws error if validation fails
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 * @param {Function} next - Express next middleware
 */
const validate = (req, res, next) => {
  // Get validation results
  const errors = validationResult(req); // Get validation errors
  
  // If validation errors exist, format and throw error
  if (!errors.isEmpty()) {
    // Format errors
    const formattedErrors = errors.array().map((error) => ({
      field: error.path || error.param, // Field name
      message: error.msg, // Error message
      value: error.value, // Invalid value
    }));
    
    // Throw validation error
    throw new ValidationError('Validation failed', formattedErrors); // Throw error
  }
  
  // Continue to next middleware
  next(); // Proceed
};

// ============================================
// Price List Validations
// ============================================

/**
 * Validation rules for creating price list
 */
const validateCreatePriceList = [
  // Validate name
  body('name')
    .notEmpty()
    .withMessage('Price list name is required')
    .trim()
    .isLength({ min: 1, max: 100 })
    .withMessage('Price list name must be between 1 and 100 characters'),
  
  // Validate code
  body('code')
    .notEmpty()
    .withMessage('Price list code is required')
    .trim()
    .isLength({ min: 1, max: 50 })
    .withMessage('Price list code must be between 1 and 50 characters')
    .matches(/^[A-Z0-9_]+$/)
    .withMessage('Price list code must contain only uppercase letters, numbers, and underscores'),
  
  // Validate price_list_type
  body('price_list_type')
    .notEmpty()
    .withMessage('Price list type is required')
    .isIn(['RETAIL', 'WHOLESALE', 'B2B', 'CUSTOMER_SPECIFIC'])
    .withMessage('Price list type must be one of: RETAIL, WHOLESALE, B2B, CUSTOMER_SPECIFIC'),
  
  // Validate currency (optional)
  body('currency')
    .optional()
    .trim()
    .isLength({ min: 3, max: 3 })
    .withMessage('Currency code must be exactly 3 characters')
    .isUppercase()
    .withMessage('Currency code must be uppercase'),
  
  // Validate description (optional)
  body('description')
    .optional()
    .trim(),
  
  // Validate is_default (optional)
  body('is_default')
    .optional()
    .isBoolean()
    .withMessage('is_default must be a boolean value')
    .toBoolean(), // Convert to boolean
  
  // Run validation
  validate, // Validate request
];

/**
 * Validation rules for updating price list
 */
const validateUpdatePriceList = [
  // Validate id parameter
  param('id')
    .notEmpty()
    .withMessage('Price list ID is required')
    .isInt({ min: 1 })
    .withMessage('Price list ID must be a positive integer')
    .toInt(), // Convert to integer
  
  // Validate name (optional)
  body('name')
    .optional()
    .trim()
    .isLength({ min: 1, max: 100 })
    .withMessage('Price list name must be between 1 and 100 characters'),
  
  // Validate code (optional)
  body('code')
    .optional()
    .trim()
    .isLength({ min: 1, max: 50 })
    .withMessage('Price list code must be between 1 and 50 characters')
    .matches(/^[A-Z0-9_]+$/)
    .withMessage('Price list code must contain only uppercase letters, numbers, and underscores'),
  
  // Validate price_list_type (optional)
  body('price_list_type')
    .optional()
    .isIn(['RETAIL', 'WHOLESALE', 'B2B', 'CUSTOMER_SPECIFIC'])
    .withMessage('Price list type must be one of: RETAIL, WHOLESALE, B2B, CUSTOMER_SPECIFIC'),
  
  // Validate currency (optional)
  body('currency')
    .optional()
    .trim()
    .isLength({ min: 3, max: 3 })
    .withMessage('Currency code must be exactly 3 characters')
    .isUppercase()
    .withMessage('Currency code must be uppercase'),
  
  // Validate description (optional)
  body('description')
    .optional()
    .trim(),
  
  // Validate is_default (optional)
  body('is_default')
    .optional()
    .isBoolean()
    .withMessage('is_default must be a boolean value')
    .toBoolean(), // Convert to boolean
  
  // Validate active (optional)
  body('active')
    .optional()
    .isBoolean()
    .withMessage('active must be a boolean value')
    .toBoolean(), // Convert to boolean
  
  // Run validation
  validate, // Validate request
];

/**
 * Validation rules for getting price list by ID
 */
const validateGetPriceList = [
  // Validate id parameter
  param('id')
    .notEmpty()
    .withMessage('Price list ID is required')
    .isInt({ min: 1 })
    .withMessage('Price list ID must be a positive integer')
    .toInt(), // Convert to integer
  
  // Run validation
  validate, // Validate request
];

/**
 * Validation rules for deleting price list
 */
const validateDeletePriceList = [
  // Validate id parameter
  param('id')
    .notEmpty()
    .withMessage('Price list ID is required')
    .isInt({ min: 1 })
    .withMessage('Price list ID must be a positive integer')
    .toInt(), // Convert to integer
  
  // Run validation
  validate, // Validate request
];

/**
 * Validation rules for listing price lists
 */
const validateListPriceLists = [
  // Validate page query parameter
  query('page')
    .optional()
    .isInt({ min: 1 })
    .withMessage('Page must be a positive integer')
    .toInt(), // Convert to integer
  
  // Validate limit query parameter
  query('limit')
    .optional()
    .isInt({ min: 1, max: 100 })
    .withMessage('Limit must be between 1 and 100')
    .toInt(), // Convert to integer
  
  // Validate price_list_type query parameter
  query('price_list_type')
    .optional()
    .isIn(['RETAIL', 'WHOLESALE', 'B2B', 'CUSTOMER_SPECIFIC'])
    .withMessage('Price list type must be one of: RETAIL, WHOLESALE, B2B, CUSTOMER_SPECIFIC'),
  
  // Validate active query parameter
  query('active')
    .optional()
    .isIn(['true', 'false'])
    .withMessage('active must be "true" or "false"'),
  
  // Run validation
  validate, // Validate request
];

// ============================================
// Product Price Validations
// ============================================

/**
 * Validation rules for creating product price
 */
const validateCreateProductPrice = [
  // Validate price_list_id
  body('price_list_id')
    .notEmpty()
    .withMessage('Price list ID is required')
    .isInt({ min: 1 })
    .withMessage('Price list ID must be a positive integer')
    .toInt(), // Convert to integer
  
  // Validate product_id
  body('product_id')
    .notEmpty()
    .withMessage('Product ID is required')
    .isInt({ min: 1 })
    .withMessage('Product ID must be a positive integer')
    .toInt(), // Convert to integer
  
  // variant_id removed - variants not used
  
  // Validate price
  body('price')
    .notEmpty()
    .withMessage('Price is required')
    .isFloat({ min: 0 })
    .withMessage('Price must be a non-negative number')
    .toFloat(), // Convert to float
  
  // Validate min_quantity (optional)
  body('min_quantity')
    .optional()
    .isFloat({ min: 0 })
    .withMessage('Minimum quantity must be a non-negative number')
    .toFloat(), // Convert to float
  
  // Validate max_quantity (optional)
  body('max_quantity')
    .optional()
    .custom((value) => {
      // Accept null or non-negative number
      if (value === null || value === 'null') return true; // Accept null
      const num = parseFloat(value); // Parse to float
      if (isNaN(num) || num < 0) throw new Error('Maximum quantity must be a non-negative number or null'); // Validate
      return true; // Validation passed
    }),
  
  // Validate effective_from (optional)
  body('effective_from')
    .optional()
    .isISO8601()
    .withMessage('Effective from date must be a valid ISO 8601 date')
    .toDate(), // Convert to date
  
  // Validate effective_to (optional)
  body('effective_to')
    .optional()
    .custom((value) => {
      // Accept null or valid ISO 8601 date
      if (value === null || value === 'null') return true; // Accept null
      if (!/^\d{4}-\d{2}-\d{2}/.test(value)) throw new Error('Effective to date must be a valid ISO 8601 date or null'); // Validate
      return true; // Validation passed
    }),
  
  // Validate active (optional)
  body('active')
    .optional()
    .isBoolean()
    .withMessage('active must be a boolean value')
    .toBoolean(), // Convert to boolean
  
  // Run validation
  validate, // Validate request
];

/**
 * Validation rules for updating product price
 */
const validateUpdateProductPrice = [
  // Validate id parameter
  param('id')
    .notEmpty()
    .withMessage('Product price ID is required')
    .isInt({ min: 1 })
    .withMessage('Product price ID must be a positive integer')
    .toInt(), // Convert to integer
  
  // Validate price (optional)
  body('price')
    .optional()
    .isFloat({ min: 0 })
    .withMessage('Price must be a non-negative number')
    .toFloat(), // Convert to float
  
  // Validate min_quantity (optional)
  body('min_quantity')
    .optional()
    .isFloat({ min: 0 })
    .withMessage('Minimum quantity must be a non-negative number')
    .toFloat(), // Convert to float
  
  // Validate max_quantity (optional)
  body('max_quantity')
    .optional()
    .custom((value) => {
      // Accept null or non-negative number
      if (value === null || value === 'null') return true; // Accept null
      const num = parseFloat(value); // Parse to float
      if (isNaN(num) || num < 0) throw new Error('Maximum quantity must be a non-negative number or null'); // Validate
      return true; // Validation passed
    }),
  
  // Validate effective_from (optional)
  body('effective_from')
    .optional()
    .isISO8601()
    .withMessage('Effective from date must be a valid ISO 8601 date')
    .toDate(), // Convert to date
  
  // Validate effective_to (optional)
  body('effective_to')
    .optional()
    .custom((value) => {
      // Accept null or valid ISO 8601 date
      if (value === null || value === 'null') return true; // Accept null
      if (!/^\d{4}-\d{2}-\d{2}/.test(value)) throw new Error('Effective to date must be a valid ISO 8601 date or null'); // Validate
      return true; // Validation passed
    }),
  
  // Validate active (optional)
  body('active')
    .optional()
    .isBoolean()
    .withMessage('active must be a boolean value')
    .toBoolean(), // Convert to boolean
  
  // Run validation
  validate, // Validate request
];

/**
 * Validation rules for getting product price by ID
 */
const validateGetProductPrice = [
  // Validate id parameter
  param('id')
    .notEmpty()
    .withMessage('Product price ID is required')
    .isInt({ min: 1 })
    .withMessage('Product price ID must be a positive integer')
    .toInt(), // Convert to integer
  
  // Run validation
  validate, // Validate request
];

/**
 * Validation rules for deleting product price
 */
const validateDeleteProductPrice = [
  // Validate id parameter
  param('id')
    .notEmpty()
    .withMessage('Product price ID is required')
    .isInt({ min: 1 })
    .withMessage('Product price ID must be a positive integer')
    .toInt(), // Convert to integer
  
  // Run validation
  validate, // Validate request
];

/**
 * Validation rules for listing product prices
 */
const validateListProductPrices = [
  // Validate page query parameter
  query('page')
    .optional()
    .isInt({ min: 1 })
    .withMessage('Page must be a positive integer')
    .toInt(), // Convert to integer
  
  // Validate limit query parameter
  query('limit')
    .optional()
    .isInt({ min: 1, max: 100 })
    .withMessage('Limit must be between 1 and 100')
    .toInt(), // Convert to integer
  
  // Validate price_list_id query parameter
  query('price_list_id')
    .optional()
    .isInt({ min: 1 })
    .withMessage('Price list ID must be a positive integer')
    .toInt(), // Convert to integer
  
  // Validate product_id query parameter
  query('product_id')
    .optional()
    .isInt({ min: 1 })
    .withMessage('Product ID must be a positive integer')
    .toInt(), // Convert to integer
  
  // variant_id removed - variants not used
  
  // Validate active query parameter
  query('active')
    .optional()
    .isIn(['true', 'false'])
    .withMessage('active must be "true" or "false"'),
  
  // Run validation
  validate, // Validate request
];

/**
 * Validation rules for getting price
 */
const validateGetPrice = [
  // Validate product_id query parameter
  query('product_id')
    .notEmpty()
    .withMessage('Product ID is required')
    .isInt({ min: 1 })
    .withMessage('Product ID must be a positive integer')
    .toInt(), // Convert to integer
  
  // variant_id removed - variants not used
  
  // Validate quantity query parameter (optional)
  query('quantity')
    .optional()
    .isFloat({ min: 0.001 })
    .withMessage('Quantity must be a positive number')
    .toFloat(), // Convert to float
  
  // Validate price_list_id query parameter (optional)
  query('price_list_id')
    .optional()
    .isInt({ min: 1 })
    .withMessage('Price list ID must be a positive integer')
    .toInt(), // Convert to integer
  
  // Run validation
  validate, // Validate request
];

/**
 * Validation rules for getting price for customer
 */
const validateGetPriceForCustomer = [
  // Validate product_id query parameter
  query('product_id')
    .notEmpty()
    .withMessage('Product ID is required')
    .isInt({ min: 1 })
    .withMessage('Product ID must be a positive integer')
    .toInt(), // Convert to integer
  
  // variant_id removed - variants not used
  
  // Validate quantity query parameter (optional)
  query('quantity')
    .optional()
    .isFloat({ min: 0.001 })
    .withMessage('Quantity must be a positive number')
    .toFloat(), // Convert to float
  
  // Validate customer_id query parameter (optional)
  query('customer_id')
    .optional()
    .isInt({ min: 1 })
    .withMessage('Customer ID must be a positive integer')
    .toInt(), // Convert to integer
  
  // Run validation
  validate, // Validate request
];

// Export validation rules
module.exports = {
  // Price list validations
  validateCreatePriceList, // Create price list validation
  validateUpdatePriceList, // Update price list validation
  validateGetPriceList, // Get price list validation
  validateDeletePriceList, // Delete price list validation
  validateListPriceLists, // List price lists validation
  // Product price validations
  validateCreateProductPrice, // Create product price validation
  validateUpdateProductPrice, // Update product price validation
  validateGetProductPrice, // Get product price validation
  validateDeleteProductPrice, // Delete product price validation
  validateListProductPrices, // List product prices validation
  validateGetPrice, // Get price validation
  validateGetPriceForCustomer, // Get price for customer validation
};

