/**
 * Test Production Order Integration with Dimension-Based Material Allocation
 * Tests the integration of production orders with dimension-based material allocation
 */

const productionOrderService = require('./modules/production/services/productionOrders');
const bomDimensionService = require('./services/bomDimensionService');
const materialAllocationService = require('./services/materialAllocationService');

// Mock data for testing
const mockProductionOrder = {
  id: 1,
  fg_variant_id: 1,
  quantity: 10,
  status: 'DRAFT'
};

const mockBOM = {
  id: 1,
  items: [
    {
      id: 1,
      rm_product_id: 1,
      use_dimensions: true,
      required_length: 150,
      required_width: 100,
      dimension_unit: 'cm',
      rawMaterial: {
        id: 1,
        name: 'Cotton Fabric',
        product_type: 'RM',
        track_by_dimensions: true,
        unit_of_measure: 'cm'
      },
      // Add method to check if dimension-based
      isDimensionBased: function() {
        return this.use_dimensions === true;
      }
    },
    {
      id: 2,
      rm_product_id: 2,
      use_dimensions: false,
      quantity_per_unit: 5,
      rawMaterial: {
        id: 2,
        name: 'Thread',
        product_type: 'RM',
        track_by_dimensions: false
      },
      // Add method to check if dimension-based
      isDimensionBased: function() {
        return this.use_dimensions === true;
      }
    }
  ]
};

const mockRMPieces = [
  {
    id: 1,
    product_id: 1,
    piece_number: 1,
    length: 200,
    width: 150,
    unit: 'cm',
    status: 'FULL',
    usable_length: null,
    usable_width: null
  },
  {
    id: 2,
    product_id: 1,
    piece_number: 2,
    length: 180,
    width: 120,
    unit: 'cm',
    status: 'USABLE',
    usable_length: 160,
    usable_width: 110
  }
];

/**
 * Test production availability check with dimensions
 */
function testProductionAvailabilityCheck() {
  console.log('\n=== Testing Production Availability Check ===');
  
  try {
    // Test dimension requirements calculation
    const dimensionReq = bomDimensionService.calculateDimensionRequirements(
      mockBOM.items[0], 
      mockProductionOrder.quantity
    );
    
    console.log('✓ Dimension Requirements Calculation:');
    console.log(`  - Area per unit: ${dimensionReq.areaPerUnit} cm²`);
    console.log(`  - Total area required: ${dimensionReq.totalAreaRequired} cm²`);
    console.log(`  - Production quantity: ${dimensionReq.productionQuantity}`);
    
    // Test BOM feasibility
    const feasibility = bomDimensionService.validateBOMFeasibility(mockBOM, mockProductionOrder.quantity);
    console.log('✓ BOM Feasibility Check completed');
    
    return {
      success: true,
      dimensionRequirements: dimensionReq,
      feasibility: feasibility
    };
  } catch (error) {
    console.error('✗ Production availability check failed:', error.message);
    return { success: false, error: error.message };
  }
}

/**
 * Test production quantity optimization
 */
function testProductionQuantityOptimization() {
  console.log('\n=== Testing Production Quantity Optimization ===');
  
  try {
    const testQuantities = [5, 10, 15, 20];
    const optimizationResults = [];
    
    for (const quantity of testQuantities) {
      // Calculate dimension requirements for this quantity
      const dimensionReq = bomDimensionService.calculateDimensionRequirements(
        mockBOM.items[0], 
        quantity
      );
      
      if (dimensionReq.isValid) {
        // Simulate material allocation
        const allocationResult = materialAllocationService.findSuitablePieces(
          mockRMPieces,
          {
            length: mockBOM.items[0].required_length,
            width: mockBOM.items[0].required_width,
            unit: mockBOM.items[0].dimension_unit
          },
          { strategy: materialAllocationService.ALLOCATION_STRATEGIES.BEST_FIT }
        );
        
        if (allocationResult.isValid && allocationResult.suitablePieces.length > 0) {
          const bestPiece = allocationResult.suitablePieces[0];
          const utilizationRatio = bestPiece.metrics.utilizationRatio;
          const wasteRatio = bestPiece.metrics.wasteRatio;
          
          optimizationResults.push({
            quantity: quantity,
            totalAreaRequired: dimensionReq.totalAreaRequired,
            utilizationRatio: utilizationRatio,
            wasteRatio: wasteRatio,
            efficiencyScore: utilizationRatio * 70 + (1 - wasteRatio) * 30,
            feasible: true
          });
        } else {
          optimizationResults.push({
            quantity: quantity,
            totalAreaRequired: dimensionReq.totalAreaRequired,
            feasible: false,
            reason: 'No suitable pieces available'
          });
        }
      }
    }
    
    // Sort by efficiency score
    const feasibleResults = optimizationResults.filter(r => r.feasible);
    feasibleResults.sort((a, b) => b.efficiencyScore - a.efficiencyScore);
    
    console.log('✓ Production Quantity Optimization Results:');
    feasibleResults.forEach((result, index) => {
      console.log(`  ${index + 1}. Quantity: ${result.quantity}`);
      console.log(`     - Total area: ${result.totalAreaRequired} cm²`);
      console.log(`     - Utilization: ${(result.utilizationRatio * 100).toFixed(1)}%`);
      console.log(`     - Waste: ${(result.wasteRatio * 100).toFixed(1)}%`);
      console.log(`     - Efficiency score: ${result.efficiencyScore.toFixed(1)}`);
    });
    
    return {
      success: true,
      optimizationResults: optimizationResults,
      recommendedQuantity: feasibleResults.length > 0 ? feasibleResults[0].quantity : null
    };
  } catch (error) {
    console.error('✗ Production quantity optimization failed:', error.message);
    return { success: false, error: error.message };
  }
}

/**
 * Test material allocation for production
 */
function testMaterialAllocationForProduction() {
  console.log('\n=== Testing Material Allocation for Production ===');
  
  try {
    // Test allocation for dimension-based BOM item
    const allocationResult = materialAllocationService.allocateMaterialForBOMItem(
      mockRMPieces,
      mockBOM.items[0],
      mockProductionOrder.quantity,
      { strategy: materialAllocationService.ALLOCATION_STRATEGIES.BEST_FIT }
    );
    
    if (allocationResult.isValid) {
      console.log('✓ Material Allocation Results:');
      console.log(`  - BOM Item: ${mockBOM.items[0].rawMaterial.name}`);
      console.log(`  - Production quantity: ${allocationResult.productionQuantity}`);
      console.log(`  - Allocated units: ${allocationResult.totalAllocatedUnits}`);
      console.log(`  - Remaining quantity: ${allocationResult.remainingQuantity}`);
      console.log(`  - Fully allocated: ${allocationResult.isFullyAllocated}`);
      console.log(`  - Pieces used: ${allocationResult.piecesUsed}`);
      console.log(`  - Total waste area: ${allocationResult.totalWasteArea} cm²`);
      console.log(`  - Utilization efficiency: ${(allocationResult.utilizationEfficiency * 100).toFixed(1)}%`);
      
      // Show allocation details
      console.log('  - Allocation details:');
      allocationResult.allocations.forEach((allocation, index) => {
        console.log(`    ${index + 1}. Piece ${allocation.piece.id}:`);
        console.log(`       - Units allocated: ${allocation.unitsAllocated}`);
        console.log(`       - Available: ${allocation.availableDimensions.length}×${allocation.availableDimensions.width} ${allocation.availableDimensions.unit}`);
        console.log(`       - Required: ${allocation.requiredDimensions.length}×${allocation.requiredDimensions.width} ${allocation.requiredDimensions.unit}`);
        console.log(`       - Remaining: ${allocation.remainingDimensions.length}×${allocation.remainingDimensions.width} ${allocation.remainingDimensions.unit}`);
        console.log(`       - Efficiency: ${(allocation.metrics.efficiencyScore).toFixed(1)}`);
      });
    } else {
      console.error('✗ Material allocation failed:', allocationResult.error);
      return { success: false, error: allocationResult.error };
    }
    
    return {
      success: true,
      allocationResult: allocationResult
    };
  } catch (error) {
    console.error('✗ Material allocation for production failed:', error.message);
    return { success: false, error: error.message };
  }
}

/**
 * Test mixed BOM production (dimension + quantity based)
 */
function testMixedBOMProduction() {
  console.log('\n=== Testing Mixed BOM Production ===');
  
  try {
    // Validate mixed BOM
    const mixedValidation = bomDimensionService.validateMixedBOM(mockBOM.items);
    
    console.log('✓ Mixed BOM Validation:');
    console.log(`  - Valid: ${mixedValidation.isValid}`);
    console.log(`  - Has dimension-based items: ${mixedValidation.hasDimensionBased}`);
    console.log(`  - Has quantity-based items: ${mixedValidation.hasQuantityBased}`);
    console.log(`  - Is mixed BOM: ${mixedValidation.isMixed}`);
    console.log(`  - Total items: ${mixedValidation.summary.totalItems}`);
    console.log(`  - Dimension-based items: ${mixedValidation.summary.dimensionBasedItems}`);
    console.log(`  - Quantity-based items: ${mixedValidation.summary.quantityBasedItems}`);
    
    // Generate requirements summary
    const requirementsSummary = bomDimensionService.generateDimensionRequirementsSummary(
      mockBOM, 
      mockProductionOrder.quantity
    );
    
    if (requirementsSummary.isValid) {
      console.log('✓ Requirements Summary:');
      console.log(`  - Production quantity: ${requirementsSummary.summary.productionQuantity}`);
      console.log(`  - Total area required: ${requirementsSummary.summary.totalAreaRequired} cm²`);
      
      console.log('  - Dimension-based items:');
      requirementsSummary.summary.dimensionBasedItems.forEach((item, index) => {
        console.log(`    ${index + 1}. ${item.productName}:`);
        console.log(`       - Dimensions: ${item.dimensions.length}×${item.dimensions.width} ${item.dimensions.unit}`);
        console.log(`       - Area per unit: ${item.areaPerUnit} cm²`);
        console.log(`       - Total area: ${item.totalAreaRequired} cm²`);
      });
      
      console.log('  - Quantity-based items:');
      requirementsSummary.summary.quantityBasedItems.forEach((item, index) => {
        console.log(`    ${index + 1}. ${item.productName}:`);
        console.log(`       - Quantity per unit: ${item.quantityPerUnit}`);
        console.log(`       - Total quantity: ${item.totalQuantityRequired}`);
      });
      
      console.log('  - Unit breakdown:');
      Object.entries(requirementsSummary.summary.unitBreakdown).forEach(([unit, area]) => {
        console.log(`    - ${unit}: ${area} area units`);
      });
    }
    
    return {
      success: true,
      mixedValidation: mixedValidation,
      requirementsSummary: requirementsSummary
    };
  } catch (error) {
    console.error('✗ Mixed BOM production test failed:', error.message);
    return { success: false, error: error.message };
  }
}

/**
 * Test production workflow simulation
 */
function testProductionWorkflowSimulation() {
  console.log('\n=== Testing Production Workflow Simulation ===');
  
  try {
    console.log('Production Order Details:');
    console.log(`  - ID: ${mockProductionOrder.id}`);
    console.log(`  - FG Variant: ${mockProductionOrder.fg_variant_id}`);
    console.log(`  - Quantity: ${mockProductionOrder.quantity}`);
    console.log(`  - Status: ${mockProductionOrder.status}`);
    
    console.log('\nBOM Analysis:');
    console.log(`  - BOM ID: ${mockBOM.id}`);
    console.log(`  - Total items: ${mockBOM.items.length}`);
    console.log(`  - Dimension-based items: ${mockBOM.items.filter(item => item.use_dimensions).length}`);
    console.log(`  - Quantity-based items: ${mockBOM.items.filter(item => !item.use_dimensions).length}`);
    
    console.log('\nAvailable RM Pieces:');
    mockRMPieces.forEach((piece, index) => {
      console.log(`  ${index + 1}. Piece ${piece.id}:`);
      console.log(`     - Dimensions: ${piece.length}×${piece.width} ${piece.unit}`);
      console.log(`     - Status: ${piece.status}`);
      if (piece.status === 'USABLE') {
        console.log(`     - Usable: ${piece.usable_length}×${piece.usable_width} ${piece.unit}`);
      }
    });
    
    // Simulate production confirmation workflow
    console.log('\nSimulating Production Confirmation Workflow:');
    
    // Step 1: Check availability
    console.log('  1. Checking material availability...');
    const availabilityTest = testProductionAvailabilityCheck();
    
    if (!availabilityTest.success) {
      throw new Error(`Availability check failed: ${availabilityTest.error}`);
    }
    
    // Step 2: Optimize production quantity
    console.log('  2. Optimizing production quantity...');
    const optimizationTest = testProductionQuantityOptimization();
    
    if (!optimizationTest.success) {
      throw new Error(`Optimization failed: ${optimizationTest.error}`);
    }
    
    // Step 3: Allocate materials
    console.log('  3. Allocating materials...');
    const allocationTest = testMaterialAllocationForProduction();
    
    if (!allocationTest.success) {
      throw new Error(`Material allocation failed: ${allocationTest.error}`);
    }
    
    // Step 4: Validate mixed BOM
    console.log('  4. Validating mixed BOM...');
    const mixedBOMTest = testMixedBOMProduction();
    
    if (!mixedBOMTest.success) {
      throw new Error(`Mixed BOM validation failed: ${mixedBOMTest.error}`);
    }
    
    console.log('\n✓ Production workflow simulation completed successfully!');
    
    return {
      success: true,
      workflow: {
        availability: availabilityTest,
        optimization: optimizationTest,
        allocation: allocationTest,
        mixedBOM: mixedBOMTest
      }
    };
  } catch (error) {
    console.error('✗ Production workflow simulation failed:', error.message);
    return { success: false, error: error.message };
  }
}

/**
 * Run all production integration tests
 */
function runProductionIntegrationTests() {
  console.log('🧪 PRODUCTION ORDER DIMENSION INTEGRATION TESTS');
  console.log('================================================');
  
  const results = {
    availabilityCheck: testProductionAvailabilityCheck(),
    quantityOptimization: testProductionQuantityOptimization(),
    materialAllocation: testMaterialAllocationForProduction(),
    mixedBOMProduction: testMixedBOMProduction(),
    workflowSimulation: testProductionWorkflowSimulation()
  };
  
  // Summary
  console.log('\n📊 TEST SUMMARY');
  console.log('================');
  
  const testNames = Object.keys(results);
  const passedTests = testNames.filter(name => results[name].success);
  const failedTests = testNames.filter(name => !results[name].success);
  
  console.log(`✅ Passed: ${passedTests.length}/${testNames.length}`);
  console.log(`❌ Failed: ${failedTests.length}/${testNames.length}`);
  
  if (failedTests.length > 0) {
    console.log('\nFailed Tests:');
    failedTests.forEach(testName => {
      console.log(`  - ${testName}: ${results[testName].error}`);
    });
  }
  
  if (passedTests.length === testNames.length) {
    console.log('\n🎉 All production integration tests passed!');
    console.log('\nKey Features Validated:');
    console.log('✓ Dimension-based material availability checking');
    console.log('✓ Production quantity optimization suggestions');
    console.log('✓ Intelligent material allocation for production');
    console.log('✓ Mixed BOM support (dimension + quantity based)');
    console.log('✓ Complete production workflow simulation');
  } else {
    console.log('\n⚠️  Some tests failed. Please review the implementation.');
  }
  
  return results;
}

// Run tests if this file is executed directly
if (require.main === module) {
  runProductionIntegrationTests();
}

module.exports = {
  runProductionIntegrationTests,
  testProductionAvailabilityCheck,
  testProductionQuantityOptimization,
  testMaterialAllocationForProduction,
  testMixedBOMProduction,
  testProductionWorkflowSimulation
};