/**
 * Production Validation Rules
 * Input validation rules for production 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
};

// ============================================
// BOM Validations
// ============================================

/**
 * Validate create BOM request
 */
const validateCreateBOM = [
  // Validate fg_product_id (required)
  body('fg_product_id')
    .notEmpty()
    .withMessage('Finished good product ID is required')
    .isInt({ min: 1 })
    .withMessage('Finished good product ID must be a positive integer'),
  
  // category and type removed - derived from Product in backend
  
  // Validate items (required, array)
  body('items')
    .isArray({ min: 1 })
    .withMessage('BOM must have at least one item')
    .custom((items) => {
      // Validate each item
      for (const item of items) {
        // Check if rm_product_id exists
        if (!item.rm_product_id) {
          throw new Error('BOM item must have rm_product_id'); // Throw error if missing
        }
        
        // Validate item_type if provided (optional but recommended)
        if (item.item_type !== undefined && item.item_type !== null) {
          const validItemTypes = ['FABRIC', 'BUTTONS', 'ZIPPER', 'LINING', 'ELASTIC'];
          if (!validItemTypes.includes(item.item_type)) {
            throw new Error(`item_type must be one of: ${validItemTypes.join(', ')}`); // Throw error if invalid
          }
        }
        
        // Determine if item is dimension-based or quantity-based from fields
        // use_dimensions removed - derive from field presence
        const hasDimensions = item.required_length !== undefined && 
                              item.required_length !== null && 
                              item.required_width !== undefined && 
                              item.required_width !== null && 
                              item.dimension_unit !== undefined && 
                              item.dimension_unit !== null;
        
        const hasQuantity = item.quantity_per_unit !== undefined && item.quantity_per_unit !== null;
        
        // Validate: must be either dimension-based OR quantity-based, not both, not neither
        if (hasDimensions && hasQuantity) {
          throw new Error('BOM item cannot have both dimension fields and quantity_per_unit');
        }
        
        if (!hasDimensions && !hasQuantity) {
          throw new Error('BOM item must have either dimension fields (required_length, required_width, dimension_unit) or quantity_per_unit');
        }
        
        if (hasDimensions) {
          // Dimension-based validation
          if (parseFloat(item.required_length) <= 0 || parseFloat(item.required_width) <= 0) {
            throw new Error('Required dimensions must be positive numbers');
          }
          if (!['inch', 'cm', 'm'].includes(item.dimension_unit)) {
            throw new Error('Dimension unit must be one of: inch, cm, m');
          }
        } else {
          // Quantity-based validation
          if (parseFloat(item.quantity_per_unit) <= 0) {
            throw new Error('quantity_per_unit must be greater than 0'); // Throw error if invalid
          }
        }
      }
      return true; // Return true if valid
    }),
  
  // Validate each item's rm_product_id
  body('items.*.rm_product_id')
    .isInt({ min: 1 })
    .withMessage('Raw material product ID must be a positive integer'),
  
  // use_dimensions removed - derived from Product.track_by_dimensions in backend
  
  // Validate each item's quantity_per_unit (for quantity-based items)
  body('items.*.quantity_per_unit')
    .optional()
    .isFloat({ min: 0.001 })
    .withMessage('Quantity per unit must be a positive number'),
  
  // Validate dimension fields (for dimension-based items)
  body('items.*.required_length')
    .optional()
    .isFloat({ min: 0.001 })
    .withMessage('Required length must be a positive number'),
  
  body('items.*.required_width')
    .optional()
    .isFloat({ min: 0.001 })
    .withMessage('Required width must be a positive number'),
  
  body('items.*.dimension_unit')
    .optional()
    .isIn(['inch', 'cm', 'm'])
    .withMessage('Dimension unit must be one of: inch, cm, m'),
  
  // Handle validation errors
  handleValidationErrors,
];

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

/**
 * Validate get BOM by product ID request (DEPRECATED - kept for backward compatibility)
 */
const validateGetBOMByProduct = [
  // Validate productId parameter (required)
  param('productId')
    .isInt({ min: 1 })
    .withMessage('Product ID must be a positive integer'),
  
  // Handle validation errors
  handleValidationErrors,
];

/**
 * Validate update BOM request
 */
const validateUpdateBOM = [
  // Validate id parameter (required)
  param('id')
    .isInt({ min: 1 })
    .withMessage('BOM ID must be a positive integer'),
  
  // Validate items (optional, array if provided)
  body('items')
    .optional()
    .isArray({ min: 1 })
    .withMessage('BOM must have at least one item if items are provided')
    .custom((items) => {
      // Validate each item
      for (const item of items) {
        // Check if rm_product_id exists
        if (!item.rm_product_id) {
          throw new Error('BOM item must have rm_product_id'); // Throw error if missing
        }
        
        // Determine if item is dimension-based or quantity-based from fields
        // use_dimensions removed - derive from field presence
        const hasDimensions = item.required_length !== undefined && 
                              item.required_length !== null && 
                              item.required_width !== undefined && 
                              item.required_width !== null && 
                              item.dimension_unit !== undefined && 
                              item.dimension_unit !== null;
        
        const hasQuantity = item.quantity_per_unit !== undefined && item.quantity_per_unit !== null;
        
        // Validate: must be either dimension-based OR quantity-based, not both, not neither
        if (hasDimensions && hasQuantity) {
          throw new Error('BOM item cannot have both dimension fields and quantity_per_unit');
        }
        
        if (!hasDimensions && !hasQuantity) {
          throw new Error('BOM item must have either dimension fields (required_length, required_width, dimension_unit) or quantity_per_unit');
        }
        
        if (hasDimensions) {
          // Dimension-based validation
          if (parseFloat(item.required_length) <= 0 || parseFloat(item.required_width) <= 0) {
            throw new Error('Required dimensions must be positive numbers');
          }
          if (!['inch', 'cm', 'm'].includes(item.dimension_unit)) {
            throw new Error('Dimension unit must be one of: inch, cm, m');
          }
        } else {
          // Quantity-based validation
          if (parseFloat(item.quantity_per_unit) <= 0) {
            throw new Error('quantity_per_unit must be greater than 0'); // Throw error if invalid
          }
        }
      }
      return true; // Return true if valid
    }),
  
  // Validate each item's rm_product_id (if items provided)
  body('items.*.rm_product_id')
    .optional()
    .isInt({ min: 1 })
    .withMessage('Raw material product ID must be a positive integer'),
  
  // use_dimensions removed - derived from Product.track_by_dimensions in backend
  // category and type removed - derived from Product in backend
  
  // Validate each item's quantity_per_unit (if items provided)
  body('items.*.quantity_per_unit')
    .optional()
    .isFloat({ min: 0.001 })
    .withMessage('Quantity per unit must be a positive number'),
  
  // Validate dimension fields (for dimension-based items)
  body('items.*.required_length')
    .optional()
    .isFloat({ min: 0.001 })
    .withMessage('Required length must be a positive number'),
  
  body('items.*.required_width')
    .optional()
    .isFloat({ min: 0.001 })
    .withMessage('Required width must be a positive number'),
  
  body('items.*.dimension_unit')
    .optional()
    .isIn(['inch', 'cm', 'm'])
    .withMessage('Dimension unit must be one of: inch, cm, m'),
  
  // Handle validation errors
  handleValidationErrors,
];

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

/**
 * Validate list BOMs request
 */
const validateListBOMs = [
  // Validate fg_product_id query parameter (optional)
  query('fg_product_id')
    .optional()
    .isInt({ min: 1 })
    .withMessage('Finished good product ID must be a positive integer'),
  
  // 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,
];

// ============================================
// Production Order Validations
// ============================================

/**
 * Validate create production order request
 */
const validateCreateProductionOrder = [
  // Validate fg_product_id (required)
  body('fg_product_id')
    .notEmpty()
    .withMessage('Finished good product ID is required')
    .isInt({ min: 1 })
    .withMessage('Finished good product ID must be a positive integer'),
  
  // Validate quantity (required)
  body('quantity')
    .notEmpty()
    .withMessage('Quantity is required')
    .isFloat({ min: 0.001 })
    .withMessage('Quantity must be a positive number'),
  
  // Validate status (optional)
  body('status')
    .optional()
    .isIn(['DRAFT', 'CONFIRMED'])
    .withMessage('Status must be either DRAFT or CONFIRMED'),
  
  // Handle validation errors
  handleValidationErrors,
];

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

/**
 * Validate list production orders request
 */
const validateListProductionOrders = [
  // Validate fg_product_id query parameter (optional)
  query('fg_product_id')
    .optional()
    .isInt({ min: 1 })
    .withMessage('Finished good product ID must be a positive integer'),
  
  // Validate status query parameter (optional)
  query('status')
    .optional()
    .isIn(['DRAFT', 'CONFIRMED'])
    .withMessage('Status must be either DRAFT or CONFIRMED'),
  
  // 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 check availability request
 */
const validateCheckAvailability = [
  // Validate id parameter (required)
  param('id')
    .isInt({ min: 1 })
    .withMessage('Production order ID must be a positive integer'),
  
  // Handle validation errors
  handleValidationErrors,
];

/**
 * Validate confirm production request
 */
const validateConfirmProduction = [
  // Validate id parameter (required)
  param('id')
    .isInt({ min: 1 })
    .withMessage('Production order ID must be a positive integer'),
  
  // Validate generateUIDs body parameter (optional)
  body('generateUIDs')
    .optional()
    .isBoolean()
    .withMessage('generateUIDs must be a boolean'),
  
  // Validate confirmQuantity body parameter (optional - for partial confirmation)
  body('confirmQuantity')
    .optional()
    .isInt({ min: 1 })
    .withMessage('confirmQuantity must be a positive whole number (integer)'),
  
  // Handle validation errors
  handleValidationErrors,
];

// Export all validations
module.exports = {
  // BOM validations
  validateCreateBOM,
  validateGetBOM,
  validateGetBOMByProduct,
  validateUpdateBOM,
  validateDeleteBOM,
  validateListBOMs,
  // Production order validations
  validateCreateProductionOrder,
  validateGetProductionOrder,
  validateListProductionOrders,
  validateCheckAvailability,
  validateConfirmProduction,
};
