/**
 * Inventory Service Unit Tests
 * Unit tests for inventory service functions
 */

// Import inventory service
const inventoryService = require('../../../modules/inventory/services');
// Import models
const { Inventory, Product, ProductVariant } = require('../../../models');
// Import custom errors
const { NotFoundError, ValidationError, InventoryError } = require('../../../utils/errors');
// Import database helpers
const { setupTestDb, cleanupTestDb, clearTables } = require('../../helpers/dbHelpers');

/**
 * Inventory Service Tests
 */
describe('Inventory Service', () => {
  // Setup before all tests
  beforeAll(async () => {
    // Setup test database
    await setupTestDb(); // Setup test database
  });
  
  // Cleanup after all tests
  afterAll(async () => {
    // Cleanup test database
    await cleanupTestDb(); // Cleanup test database
  });
  
  // Clear tables before each test
  beforeEach(async () => {
    // Clear all tables
    await clearTables(); // Clear tables
  });
  
  /**
   * getQuantity Tests
   */
  describe('getQuantity', () => {
    // Test getting quantity for existing inventory
    it('should return quantity for existing inventory', async () => {
      // Create product
      const product = await Product.create({
        name: 'Test Product', // Product name
        sku: 'TEST-001', // SKU
        product_type: 'FG', // Product type
        track_inventory: true, // Track inventory
      }); // Create product
      
      // Create inventory
      await Inventory.create({
        product_id: product.id, // Product ID
        quantity: 100, // Quantity
        reorder_level: 10, // Reorder level
      }); // Create inventory
      
      // Get quantity
      const quantity = await inventoryService.getQuantity(product.id); // Get quantity
      
      // Verify quantity
      expect(quantity).toBe(100); // Quantity should be 100
    });
    
    // Test getting quantity for non-existent inventory
    it('should return 0 for non-existent inventory', async () => {
      // Create product
      const product = await Product.create({
        name: 'Test Product', // Product name
        sku: 'TEST-001', // SKU
        product_type: 'FG', // Product type
        track_inventory: true, // Track inventory
      }); // Create product
      
      // Get quantity (no inventory created)
      const quantity = await inventoryService.getQuantity(product.id); // Get quantity
      
      // Verify quantity
      expect(quantity).toBe(0); // Quantity should be 0
    });
  });
  
  /**
   * adjustQuantity Tests
   */
  describe('adjustQuantity', () => {
    // Test adjusting quantity (increase)
    it('should increase quantity correctly', async () => {
      // Create product
      const product = await Product.create({
        name: 'Test Product', // Product name
        sku: 'TEST-001', // SKU
        product_type: 'FG', // Product type
        track_inventory: true, // Track inventory
      }); // Create product
      
      // Create inventory with initial quantity
      await Inventory.create({
        product_id: product.id, // Product ID
        quantity: 100, // Initial quantity
        reorder_level: 10, // Reorder level
      }); // Create inventory
      
      // Adjust quantity (increase by 50)
      await inventoryService.adjustQuantity(product.id, 50, 'ADJUSTMENT', 1); // Adjust quantity
      
      // Get updated quantity
      const quantity = await inventoryService.getQuantity(product.id); // Get quantity
      
      // Verify quantity
      expect(quantity).toBe(150); // Quantity should be 150 (100 + 50)
    });
    
    // Test adjusting quantity (decrease)
    it('should decrease quantity correctly', async () => {
      // Create product
      const product = await Product.create({
        name: 'Test Product', // Product name
        sku: 'TEST-001', // SKU
        product_type: 'FG', // Product type
        track_inventory: true, // Track inventory
      }); // Create product
      
      // Create inventory with initial quantity
      await Inventory.create({
        product_id: product.id, // Product ID
        quantity: 100, // Initial quantity
        reorder_level: 10, // Reorder level
      }); // Create inventory
      
      // Adjust quantity (decrease by 30)
      await inventoryService.adjustQuantity(product.id, -30, 'ADJUSTMENT', 1); // Adjust quantity
      
      // Get updated quantity
      const quantity = await inventoryService.getQuantity(product.id); // Get quantity
      
      // Verify quantity
      expect(quantity).toBe(70); // Quantity should be 70 (100 - 30)
    });
    
    // Test adjusting quantity with insufficient stock
    it('should throw error when quantity goes negative', async () => {
      // Create product
      const product = await Product.create({
        name: 'Test Product', // Product name
        sku: 'TEST-001', // SKU
        product_type: 'FG', // Product type
        track_inventory: true, // Track inventory
      }); // Create product
      
      // Create inventory with initial quantity
      await Inventory.create({
        product_id: product.id, // Product ID
        quantity: 50, // Initial quantity
        reorder_level: 10, // Reorder level
      }); // Create inventory
      
      // Attempt to adjust quantity (decrease by 100 - more than available)
      await expect(
        inventoryService.adjustQuantity(product.id, -100, 'ADJUSTMENT', 1) // Adjust quantity
      ).rejects.toThrow(InventoryError); // Should throw InventoryError
    });
  });
  
  /**
   * checkAvailability Tests
   */
  describe('checkAvailability', () => {
    // Test checking availability with sufficient stock
    it('should return true when sufficient stock available', async () => {
      // Create product
      const product = await Product.create({
        name: 'Test Product', // Product name
        sku: 'TEST-001', // SKU
        product_type: 'FG', // Product type
        track_inventory: true, // Track inventory
      }); // Create product
      
      // Create inventory
      await Inventory.create({
        product_id: product.id, // Product ID
        quantity: 100, // Quantity
        reorder_level: 10, // Reorder level
      }); // Create inventory
      
      // Check availability
      const available = await inventoryService.checkAvailability(product.id, 50); // Check availability
      
      // Verify availability
      expect(available).toBe(true); // Should be available
    });
    
    // Test checking availability with insufficient stock
    it('should return false when insufficient stock available', async () => {
      // Create product
      const product = await Product.create({
        name: 'Test Product', // Product name
        sku: 'TEST-001', // SKU
        product_type: 'FG', // Product type
        track_inventory: true, // Track inventory
      }); // Create product
      
      // Create inventory
      await Inventory.create({
        product_id: product.id, // Product ID
        quantity: 50, // Quantity
        reorder_level: 10, // Reorder level
      }); // Create inventory
      
      // Check availability
      const available = await inventoryService.checkAvailability(product.id, 100); // Check availability
      
      // Verify availability
      expect(available).toBe(false); // Should not be available
    });
  });
});

