/**
 * Product Validation Rules
 * Input validation rules for product management 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 wrapper
 * Checks validation results and returns errors if validation fails
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 * @param {Function} next - Express next middleware function
 */
const validate = (req, res, next) => {
  // Get validation errors from request
  const errors = validationResult(req);
  
  // If validation errors exist, return error response
  if (!errors.isEmpty()) {
    // Format validation 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 with formatted errors
    throw new ValidationError('Validation failed', formattedErrors);
  }
  
  // If validation passes, proceed to next middleware
  next();
};

/**
 * Create product validation rules
 * Validates product data for product creation
 */
const validateCreateProduct = [
  // Validate name field
  body('name')
    .trim() // Remove whitespace
    .notEmpty() // Name is required
    .withMessage('Product name is required') // Error message
    .isLength({ min: 1, max: 150 }) // Name length validation
    .withMessage('Product name must be between 1 and 150 characters'), // Error message
  
  // Validate SKU field (optional)
  body('sku')
    .optional() // Field is optional
    .trim() // Remove whitespace
    .isLength({ max: 100 }) // SKU length validation
    .withMessage('SKU must not exceed 100 characters'), // Error message
  
  // Validate product_type field
  body('product_type')
    .notEmpty() // Product type is required
    .withMessage('Product type is required') // Error message
    .isIn(['FG', 'RM']) // Product type must be FG or RM
    .withMessage('Product type must be either FG (Finished Goods) or RM (Raw Materials)'), // Error message
  
  // Validate track_inventory field (optional)
  body('track_inventory')
    .optional() // Field is optional
    .isBoolean() // Track inventory must be boolean
    .withMessage('Track inventory must be a boolean value'), // Error message
  
  // Validate description field (optional)
  body('description')
    .optional() // Field is optional
    .trim(), // Remove whitespace
  
  // Validate selling_price field (optional)
  body('selling_price')
    .optional() // Field is optional
    .isFloat({ min: 0 }) // Selling price must be a non-negative number
    .withMessage('Selling price must be a non-negative number'), // Error message
  
  // Validate low_stock_threshold field (optional)
  body('low_stock_threshold')
    .optional() // Field is optional
    .isFloat({ min: 0 }) // Low stock threshold must be a non-negative number
    .withMessage('Low stock threshold must be a non-negative number'), // Error message
  
  // Run validation middleware
  validate,
];

/**
 * Update product validation rules
 * Validates product data for product updates
 */
const validateUpdateProduct = [
  // Validate product ID parameter
  param('id')
    .isInt({ min: 1 }) // Product ID must be a positive integer
    .withMessage('Invalid product ID'), // Error message
  
  // Validate name field (optional)
  body('name')
    .optional() // Field is optional
    .trim() // Remove whitespace
    .isLength({ min: 1, max: 150 }) // Name length validation
    .withMessage('Product name must be between 1 and 150 characters'), // Error message
  
  // Validate SKU field (optional)
  body('sku')
    .optional() // Field is optional
    .trim() // Remove whitespace
    .isLength({ max: 100 }) // SKU length validation
    .withMessage('SKU must not exceed 100 characters'), // Error message
  
  // Validate product_type field (optional)
  body('product_type')
    .optional() // Field is optional
    .isIn(['FG', 'RM']) // Product type must be FG or RM
    .withMessage('Product type must be either FG (Finished Goods) or RM (Raw Materials)'), // Error message
  
  // Validate track_inventory field (optional)
  body('track_inventory')
    .optional() // Field is optional
    .isBoolean() // Track inventory must be boolean
    .withMessage('Track inventory must be a boolean value'), // Error message
  
  // Validate description field (optional)
  body('description')
    .optional() // Field is optional
    .trim(), // Remove whitespace
  
  // Validate low_stock_threshold field (optional)
  body('low_stock_threshold')
    .optional() // Field is optional
    .isFloat({ min: 0 }) // Low stock threshold must be a non-negative number
    .withMessage('Low stock threshold must be a non-negative number'), // Error message
  
  // Run validation middleware
  validate,
];

/**
 * Get product validation rules
 * Validates product ID parameter
 */
const validateGetProduct = [
  // Validate product ID parameter
  param('id')
    .isInt({ min: 1 }) // Product ID must be a positive integer
    .withMessage('Invalid product ID'), // Error message
  
  // Run validation middleware
  validate,
];

/**
 * Delete product validation rules
 * Validates product ID parameter for deletion
 */
const validateDeleteProduct = [
  // Validate product ID parameter
  param('id')
    .isInt({ min: 1 }) // Product ID must be a positive integer
    .withMessage('Invalid product ID'), // Error message
  
  // Run validation middleware
  validate,
];

/**
 * List products validation rules
 * Validates query parameters for product listing
 */
const validateListProducts = [
  // Validate page query parameter (optional)
  query('page')
    .optional() // Field is optional
    .isInt({ min: 1 }) // Page must be a positive integer
    .withMessage('Page must be a positive integer'), // Error message
  
  // Validate limit query parameter (optional)
  query('limit')
    .optional() // Field is optional
    .isInt({ min: 1, max: 100 }) // Limit must be between 1 and 100
    .withMessage('Limit must be between 1 and 100'), // Error message
  
  // Validate search query parameter (optional)
  query('search')
    .optional() // Field is optional
    .trim(), // Remove whitespace
  
  // Validate product_type query parameter (optional)
  query('product_type')
    .optional() // Field is optional
    .isIn(['FG', 'RM']) // Product type must be FG or RM
    .withMessage('Product type must be either FG or RM'), // Error message
  
  // Validate track_inventory query parameter (optional)
  query('track_inventory')
    .optional() // Field is optional
    .isIn(['true', 'false']) // Track inventory must be 'true' or 'false' string
    .withMessage('Track inventory must be "true" or "false"'), // Error message
  
  // Validate sell_on_pos query parameter (optional)
  query('sell_on_pos')
    .optional() // Field is optional
    .isIn(['true', 'false']) // Sell on POS must be 'true' or 'false' string
    .withMessage('Sell on POS must be "true" or "false"'), // Error message
  
  // Validate category_id query parameter (optional)
  query('category_id')
    .optional() // Field is optional
    .isInt({ min: 1 }) // Category ID must be a positive integer
    .withMessage('Category ID must be a positive integer'), // Error message
  
  // Validate ids query parameter (optional - can be array or comma-separated string)
  query('ids')
    .optional() // Field is optional
    .custom((value) => {
      // Accept array or string
      if (Array.isArray(value)) {
        // Validate each ID in array
        for (const id of value) {
          const numId = parseInt(id, 10);
          if (isNaN(numId) || numId < 1) {
            throw new Error('All IDs must be positive integers');
          }
        }
        return true;
      }
      if (typeof value === 'string') {
        // Validate comma-separated string
        const ids = value.split(',').map(id => id.trim());
        for (const id of ids) {
          const numId = parseInt(id, 10);
          if (isNaN(numId) || numId < 1) {
            throw new Error('All IDs must be positive integers');
          }
        }
        return true;
      }
      return true; // Allow other types (will be handled in controller)
    }),
  
  // Validate include query parameter (optional - can be array or comma-separated string)
  query('include')
    .optional() // Field is optional
    .custom((value) => {
      // Accept array or string
      if (Array.isArray(value)) {
        // Validate each include value
        const validIncludes = ['prices', 'inventory', 'variants', 'categories'];
        for (const inc of value) {
          if (typeof inc !== 'string' || inc.trim().length === 0) {
            throw new Error('Include values must be non-empty strings');
          }
        }
        return true;
      }
      if (typeof value === 'string') {
        // Validate comma-separated string
        const includes = value.split(',').map(inc => inc.trim()).filter(Boolean);
        if (includes.length === 0) {
          throw new Error('Include must contain at least one value');
        }
        return true;
      }
      return true; // Allow other types (will be handled in controller)
    }),
  
  // Validate price_list_id query parameter (optional)
  query('price_list_id')
    .optional() // Field is optional
    .isInt({ min: 1 }) // Price list ID must be a positive integer
    .withMessage('Price list ID must be a positive integer'), // Error message
  
  // Validate quantity query parameter (optional)
  query('quantity')
    .optional() // Field is optional
    .isFloat({ min: 0 }) // Quantity must be a non-negative number
    .withMessage('Quantity must be a non-negative number'), // Error message
  
  // Run validation middleware
  validate,
];

/**
 * Search products validation rules
 * Validates query parameters for product search
 */
const validateSearchProducts = [
  // Validate search query parameter
  query('q')
    .optional() // Field is optional (q or search)
    .trim(), // Remove whitespace
  query('search')
    .optional() // Field is optional (q or search)
    .trim(), // Remove whitespace
  
  // Validate limit query parameter (optional)
  query('limit')
    .optional() // Field is optional
    .isInt({ min: 1, max: 100 }) // Limit must be between 1 and 100
    .withMessage('Limit must be between 1 and 100'), // Error message
  
  // Custom validation: at least one search parameter required
  query('q').custom((value, { req }) => {
    if (!value && !req.query.search) {
      throw new Error('Search term (q or search) is required');
    }
    return true;
  }),
  
  // Run validation middleware
  validate,
];

// Variant validations removed - variants are no longer supported

// Export validation rules
module.exports = {
  validateCreateProduct, // Create product validation rules
  validateUpdateProduct, // Update product validation rules
  validateGetProduct, // Get product validation rules
  validateDeleteProduct, // Delete product validation rules
  validateListProducts, // List products validation rules
  validateSearchProducts, // Search products validation rules
};
