/**
 * Production Controllers
 * Request handlers for production operations
 */

// Import production service functions
const productionService = require('../services');
// Import async handler wrapper
const asyncHandler = require('../../../middlewares/asyncHandler');
// Import response helpers
const { success: successResponse } = require('../../../utils/response');
// Import logger
const logger = require('../../../utils/logger');

// ============================================
// BOM Controllers
// ============================================

/**
 * Create BOM
 * Creates a new BOM with items
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const createBOM = asyncHandler(async (req, res) => {
  // Extract BOM data from request body
  const bomData = req.body; // Get BOM data
  
  // Create BOM using service
  const bom = await productionService.createBOM(bomData); // Create BOM
  
  // Log BOM creation
  logger.info('BOM created', {
    bomId: bom.id,
    fgProductId: bom.fg_product_id,
    itemsCount: bom.items.length,
  });
  
  // Return success response with BOM data
  return successResponse(res, bom, 'BOM created successfully', 201); // Return success response
});

/**
 * Get BOM by ID
 * Retrieves a BOM with details
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const getBOM = asyncHandler(async (req, res) => {
  // Extract BOM ID from request params
  const { id } = req.params; // Get BOM ID
  
  // Get BOM using service
  const bom = await productionService.getBOM(parseInt(id)); // Get BOM
  
  // Return success response with BOM data
  return successResponse(res, bom, 'BOM retrieved successfully'); // Return success response
});

/**
 * Get BOM by product ID
 * Retrieves a BOM by finished good product ID
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const getBOMByProduct = asyncHandler(async (req, res) => {
  // Extract product ID from request params
  const { productId } = req.params; // Get product ID
  
  // Get BOM using service
  const bom = await productionService.getBOMByProduct(parseInt(productId)); // Get BOM by product
  
  // Return success response with BOM data
  return successResponse(res, bom, 'BOM retrieved successfully'); // Return success response
});

/**
 * Update BOM
 * Updates an existing BOM
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const updateBOM = asyncHandler(async (req, res) => {
  // Extract BOM ID from request params
  const { id } = req.params; // Get BOM ID
  // Extract update data from request body
  const updateData = req.body; // Get update data
  
  // Update BOM using service
  const bom = await productionService.updateBOM(parseInt(id), updateData); // Update BOM
  
  // Log BOM update
  logger.info('BOM updated', {
    bomId: id,
    updateData,
  });
  
  // Return success response with updated BOM data
  return successResponse(res, bom, 'BOM updated successfully'); // Return success response
});

/**
 * Delete BOM
 * Deletes a BOM
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const deleteBOM = asyncHandler(async (req, res) => {
  // Extract BOM ID from request params
  const { id } = req.params; // Get BOM ID
  
  // Delete BOM using service
  await productionService.deleteBOM(parseInt(id)); // Delete BOM
  
  // Log BOM deletion
  logger.info('BOM deleted', {
    bomId: id,
  });
  
  // Return success response
  return successResponse(res, null, 'BOM deleted successfully'); // Return success response
});

/**
 * List BOMs
 * Lists BOMs with optional filters
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const listBOMs = asyncHandler(async (req, res) => {
  // Extract query parameters
  const { fg_product_id, page, limit } = req.query; // Get query params
  
  // Build filters object
  const filters = {
    ...(fg_product_id && { fg_product_id: parseInt(fg_product_id) }), // Add fg_product_id filter if provided
  }; // Build filters
  
  // Build pagination object
  const pagination = {
    ...(page && { page }), // Add page if provided
    ...(limit && { limit }), // Add limit if provided
  }; // Build pagination
  
  // List BOMs using service
  const result = await productionService.listBOMs(filters, pagination); // List BOMs
  
  // Return success response with BOMs and pagination
  return successResponse(res, result, 'BOMs retrieved successfully'); // Return success response
});

// ============================================
// Production Order Controllers
// ============================================

/**
 * Create production order
 * Creates a new production order
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const createProductionOrder = asyncHandler(async (req, res) => {
  // Extract production order data from request body
  const poData = req.body; // Get PO data
  
  // Create production order using service
  const productionOrder = await productionService.createProductionOrder(poData); // Create PO
  
  // Log production order creation
  logger.info('Production order created', {
    poId: productionOrder.id,
    fgProductId: productionOrder.fg_product_id,
    quantity: productionOrder.quantity,
  });
  
  // Return success response with production order data
  return successResponse(res, productionOrder, 'Production order created successfully', 201); // Return success response
});

/**
 * Get production order by ID
 * Retrieves a production order with details
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const getProductionOrder = asyncHandler(async (req, res) => {
  // Extract production order ID from request params
  const { id } = req.params; // Get PO ID
  
  // Get production order using service
  const productionOrder = await productionService.getProductionOrder(parseInt(id)); // Get PO
  
  // Return success response with production order data
  return successResponse(res, productionOrder, 'Production order retrieved successfully'); // Return success response
});

/**
 * List production orders
 * Lists production orders with optional filters
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const listProductionOrders = asyncHandler(async (req, res) => {
  // Extract query parameters
  const { fg_product_id, status, page, limit } = req.query; // Get query params
  
  // Build filters object
  const filters = {
    ...(fg_product_id && { fg_product_id: parseInt(fg_product_id) }), // Add fg_product_id filter if provided
    ...(status && { status }), // Add status filter if provided
  }; // Build filters
  
  // Build pagination object
  const pagination = {
    ...(page && { page }), // Add page if provided
    ...(limit && { limit }), // Add limit if provided
  }; // Build pagination
  
  // List production orders using service
  const result = await productionService.listProductionOrders(filters, pagination); // List POs
  
  // Return success response with production orders and pagination
  return successResponse(res, result, 'Production orders retrieved successfully'); // Return success response
});

/**
 * Check raw material availability
 * Checks if sufficient raw materials are available for production
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const checkAvailability = asyncHandler(async (req, res) => {
  // Extract production order ID from request params
  const { id } = req.params; // Get PO ID
  
  // Check availability using service
  const availability = await productionService.checkAvailability(parseInt(id)); // Check availability
  
  // Return success response with availability data
  return successResponse(res, availability, 'Availability checked successfully'); // Return success response
});

/**
 * Confirm production
 * Confirms production by consuming raw materials and creating finished goods
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const confirmProduction = asyncHandler(async (req, res) => {
  // Extract production order ID from request params
  const { id } = req.params; // Get PO ID
  // Extract generateUIDs from request body (optional, default: true)
  const { generateUIDs = true, confirmQuantity = null } = req.body; // Get generateUIDs flag and confirmQuantity
  // Extract user ID from request (set by auth middleware)
  const userId = req.user.id; // Get user ID from authenticated user
  
  // Confirm production using service
  const productionOrder = await productionService.confirmProduction(parseInt(id), userId, generateUIDs, confirmQuantity); // Confirm production
  
  // Log production confirmation
  logger.info('Production confirmed', {
    poId: id,
    generateUIDs,
    confirmQuantity,
  });
  
  // Determine success message based on whether it's partial or full
  const isPartial = productionOrder.status === 'PARTIALLY_CONFIRMED';
  const message = isPartial 
    ? `Production partially confirmed: ${productionOrder.confirmed_quantity}/${productionOrder.quantity} units. ${productionOrder.remaining_quantity} units remaining.`
    : 'Production confirmed successfully';
  
  // Return success response with confirmed production order data
  return successResponse(res, productionOrder, message); // Return success response
});

/**
 * Get production optimization suggestions
 * Analyzes available materials and suggests optimal production quantities
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const getProductionOptimizationSuggestions = asyncHandler(async (req, res) => {
  // Extract production order ID from request params
  const { id } = req.params;
  // Extract options from query parameters
  const { maxSuggestions, includeWasteAnalysis } = req.query;
  
  // Get optimization suggestions using service
  const suggestions = await productionService.getProductionOptimizationSuggestions(parseInt(id), {
    maxSuggestions: maxSuggestions ? parseInt(maxSuggestions) : 5,
    includeWasteAnalysis: includeWasteAnalysis !== 'false'
  });
  
  // Return success response with suggestions
  return successResponse(res, suggestions, 'Optimization suggestions retrieved successfully');
});

/**
 * Get cutting operations for production order
 * Retrieves all cutting operations performed for a production order
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const getCuttingOperations = asyncHandler(async (req, res) => {
  // Extract production order ID from request params
  const { id } = req.params;
  
  // Get cutting operations using service
  const cuttingOperations = await productionService.getCuttingOperations(parseInt(id));
  
  // Return success response with cutting operations
  return successResponse(res, cuttingOperations, 'Cutting operations retrieved successfully');
});

/**
 * Get waste piece suggestions for production planning
 * Suggests available waste pieces that match BOM requirements
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const getWastePieceSuggestions = asyncHandler(async (req, res) => {
  // Extract production order ID from request params
  const { id } = req.params;
  
  // Get waste suggestions using service
  const wasteSuggestions = await productionService.getWastePieceSuggestions(parseInt(id));
  
  // Return success response with waste suggestions
  return successResponse(res, wasteSuggestions, 'Waste suggestions retrieved successfully');
});

/**
 * Get material traceability for production order
 * Provides complete traceability from source pieces to final products
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const getMaterialTraceability = asyncHandler(async (req, res) => {
  // Extract production order ID from request params
  const { id } = req.params;
  
  // Get material traceability using service
  const traceability = await productionService.getMaterialTraceability(parseInt(id));
  
  // Return success response with traceability data
  return successResponse(res, traceability, 'Material traceability retrieved successfully');
});

// Export all controllers
module.exports = {
  // BOM controllers
  createBOM,
  getBOM,
  getBOMByProduct,
  updateBOM,
  deleteBOM,
  listBOMs,
  // Production order controllers
  createProductionOrder,
  getProductionOrder,
  listProductionOrders,
  checkAvailability,
  confirmProduction,
  // Dimension-based production controllers
  getProductionOptimizationSuggestions,
  getCuttingOperations,
  getWastePieceSuggestions,
  getMaterialTraceability,
};
