/**
 * Procurement Controllers
 * Request handlers for procurement operations
 */

// Import procurement service functions
const procurementService = 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');

// ============================================
// Vendor Controllers
// ============================================

/**
 * Create vendor
 * Creates a new vendor
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const createVendor = asyncHandler(async (req, res) => {
  // Extract vendor data from request body
  const vendorData = req.body; // Get vendor data
  
  // Create vendor using service
  const vendor = await procurementService.createVendor(vendorData); // Create vendor
  
  // Log vendor creation
  logger.info('Vendor created', {
    vendorId: vendor.id,
    name: vendor.name,
    type: vendor.type,
  });
  
  // Return success response with vendor data
  return successResponse(res, vendor, 'Vendor created successfully', 201); // Return success response
});

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

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

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

/**
 * List vendors
 * Lists vendors with optional filters
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const listVendors = asyncHandler(async (req, res) => {
  // Extract query parameters
  const { type, search, page, limit } = req.query; // Get query params
  
  // Build filters object
  const filters = {
    ...(type && { type }), // Add type filter if provided
    ...(search && { search }), // Add search 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 vendors using service
  const result = await procurementService.listVendors(filters, pagination); // List vendors
  
  // Return success response with vendors and pagination
  return successResponse(res, result, 'Vendors retrieved successfully'); // Return success response
});

// ============================================
// Purchase Order Controllers
// ============================================

/**
 * Create purchase order
 * Creates a new purchase order
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const createPurchaseOrder = asyncHandler(async (req, res) => {
  // Extract purchase order data from request body
  const poData = req.body; // Get PO data
  
  // Create purchase order using service
  const purchaseOrder = await procurementService.createPurchaseOrder(poData); // Create PO
  
  // Log purchase order creation
  logger.info('Purchase order created', {
    poId: purchaseOrder.id,
    vendorId: purchaseOrder.vendor_id,
  });
  
  // Return success response with purchase order data
  return successResponse(res, purchaseOrder, 'Purchase order created successfully', 201); // Return success response
});

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

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

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

/**
 * List purchase orders
 * Lists purchase orders with optional filters
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const listPurchaseOrders = asyncHandler(async (req, res) => {
  // Extract query parameters
  const { vendor_id, status, page, limit } = req.query; // Get query params
  
  // Build filters object
  const filters = {
    ...(vendor_id && { vendor_id: parseInt(vendor_id) }), // Add vendor_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 purchase orders using service
  const result = await procurementService.listPurchaseOrders(filters, pagination); // List POs
  
  // Return success response with purchase orders and pagination
  return successResponse(res, result, 'Purchase orders retrieved successfully'); // Return success response
});

/**
 * Update purchase order status
 * Updates only the status of a purchase order
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const updatePurchaseOrderStatus = asyncHandler(async (req, res) => {
  // Extract purchase order ID from request params
  const { id } = req.params; // Get PO ID
  // Extract status from request body
  const { status } = req.body; // Get status
  
  // Update purchase order status using service
  const purchaseOrder = await procurementService.updatePurchaseOrderStatus(parseInt(id), status); // Update status
  
  // Log purchase order status update
  logger.info('Purchase order status updated', {
    poId: id,
    status,
  });
  
  // Return success response with updated purchase order data
  return successResponse(res, purchaseOrder, 'Purchase order status updated successfully'); // Return success response
});

// ============================================
// GRN Controllers
// ============================================

/**
 * Create GRN
 * Creates a new GRN (with or without PO)
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const createGRN = asyncHandler(async (req, res) => {
  // Extract GRN data from request body
  const grnData = req.body; // Get GRN data
  // Extract user ID from request (set by auth middleware)
  const userId = req.user.id; // Get user ID from authenticated user
  
  // Create GRN using service
  const grn = await procurementService.createGRN(grnData, userId); // Create GRN
  
  // Log GRN creation
  logger.info('GRN created', {
    grnId: grn.id,
    purchaseOrderId: grn.purchase_order_id,
    vendorId: grn.vendor_id,
  });
  
  // Return success response with GRN data
  return successResponse(res, grn, 'GRN created successfully', 201); // Return success response
});

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

/**
 * List GRNs
 * Lists GRNs with optional filters
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const listGRNs = asyncHandler(async (req, res) => {
  // Extract query parameters
  const { purchase_order_id, vendor_id, po_number, status, start_date, end_date, page, limit } = req.query; // Get query params
  
  // Build filters object
  const filters = {
    ...(purchase_order_id !== undefined && { purchase_order_id: purchase_order_id === 'null' ? null : parseInt(purchase_order_id) }), // Add purchase_order_id filter if provided
    ...(vendor_id !== undefined && { vendor_id: vendor_id === 'null' ? null : parseInt(vendor_id) }), // Add vendor_id filter if provided
    ...(po_number && { po_number }), // Add PO number search filter if provided
    ...(status && { status }), // Add status filter if provided (processed, pending)
    ...(start_date && { start_date }), // Add start date filter if provided
    ...(end_date && { end_date }), // Add end date 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 GRNs using service
  const result = await procurementService.listGRNs(filters, pagination); // List GRNs
  
  // Return success response with GRNs and pagination
  return successResponse(res, result, 'GRNs retrieved successfully'); // Return success response
});

/**
 * Process GRN
 * Processes a GRN by adding stock to inventory and generating UIDs
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
const processGRN = asyncHandler(async (req, res) => {
  // Extract GRN ID from request params
  const { id } = req.params; // Get GRN ID
  // Extract generateUIDs from request body (optional, default: true)
  const { generateUIDs = true } = req.body; // Get generateUIDs flag
  // Extract user ID from request (set by auth middleware)
  const userId = req.user.id; // Get user ID from authenticated user
  
  // Process GRN using service
  const grn = await procurementService.processGRN(parseInt(id), userId, generateUIDs); // Process GRN
  
  // Log GRN processing
  logger.info('GRN processed', {
    grnId: id,
    generateUIDs,
  });
  
  // Return success response with processed GRN data
  return successResponse(res, grn, 'GRN processed successfully'); // Return success response
});

// Export all controllers
module.exports = {
  // Vendor controllers
  createVendor,
  getVendor,
  updateVendor,
  deleteVendor,
  listVendors,
  // Purchase order controllers
  createPurchaseOrder,
  getPurchaseOrder,
  updatePurchaseOrder,
  deletePurchaseOrder,
  listPurchaseOrders,
  updatePurchaseOrderStatus,
  // GRN controllers
  createGRN,
  getGRN,
  listGRNs,
  processGRN,
};
