/**
 * Test Waste and Scrap Management Integration
 * Tests the complete waste and scrap management workflow in production
 */

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

/**
 * Test complete waste management workflow
 */
function testCompleteWasteManagementWorkflow() {
  console.log('\n=== Testing Complete Waste Management Workflow ===');
  
  try {
    // Simulate a production scenario with waste generation
    const productionOrder = {
      id: 1,
      fg_variant_id: 1,
      quantity: 5,
      status: 'CONFIRMED'
    };
    
    const sourcePiece = {
      id: 1,
      product_id: 1,
      grn_item_id: 1,
      piece_number: 1,
      length: 200,
      width: 150,
      unit: 'cm',
      status: 'FULL',
      usable_length: null,
      usable_width: null,
      cost_per_area: 0.5,
      supplier_batch: 'BATCH001',
      quality_grade: 'A'
    };
    
    const cuttingData = {
      production_order_id: productionOrder.id,
      bom_item_id: 1,
      cut_length: 120,
      cut_width: 80,
      unit: 'cm',
      operator_id: 1,
      notes: 'Production cutting for waste management test'
    };
    
    console.log('✓ Step 1: Process cutting operation with waste generation');
    const cuttingResult = cuttingOperationsService.processCuttingOperation(
      cuttingData,
      sourcePiece,
      { generateWastePieces: true, autoClassifyWaste: true }
    );
    
    if (!cuttingResult.isValid) {
      throw new Error(`Cutting operation failed: ${cuttingResult.error}`);
    }
    
    console.log(`  - Cut area: ${cuttingResult.cutCalculations.cutArea} cm²`);
    console.log(`  - Remaining area: ${cuttingResult.cutCalculations.remainingArea} cm²`);
    console.log(`  - Utilization ratio: ${(cuttingResult.cutCalculations.utilizationRatio * 100).toFixed(1)}%`);
    console.log(`  - Waste pieces generated: ${cuttingResult.newWastePieces.length}`);
    
    if (cuttingResult.newWastePieces.length > 0) {
      cuttingResult.newWastePieces.forEach((waste, index) => {
        console.log(`    ${index + 1}. ${waste.length}×${waste.width} ${waste.unit} (${waste.status})`);
      });
    }
    
    console.log('✓ Step 2: Validate waste piece properties');
    if (cuttingResult.newWastePieces.length > 0) {
      const wastePiece = cuttingResult.newWastePieces[0];
      
      // Validate traceability properties
      if (!wastePiece.parent_piece_id || wastePiece.parent_piece_id !== sourcePiece.id) {
        throw new Error('Waste piece missing parent_piece_id traceability');
      }
      
      if (!wastePiece.created_from_cutting) {
        throw new Error('Waste piece missing created_from_cutting flag');
      }
      
      if (wastePiece.product_id !== sourcePiece.product_id) {
        throw new Error('Waste piece product_id does not match source');
      }
      
      if (wastePiece.grn_item_id !== sourcePiece.grn_item_id) {
        throw new Error('Waste piece grn_item_id does not match source');
      }
      
      console.log(`  - Waste piece traceability: ✓ Valid`);
      console.log(`  - Parent piece ID: ${wastePiece.parent_piece_id}`);
      console.log(`  - Created from cutting: ${wastePiece.created_from_cutting}`);
      console.log(`  - Inherited properties: ✓ Valid`);
    }
    
    console.log('✓ Step 3: Test waste piece classification');
    if (cuttingResult.newWastePieces.length > 0) {
      const wastePiece = cuttingResult.newWastePieces[0];
      const minDimensions = cuttingOperationsService.MIN_REUSABLE_DIMENSIONS[wastePiece.unit];
      
      const isReusableSize = wastePiece.length >= minDimensions.length && 
                            wastePiece.width >= minDimensions.width;
      
      const expectedStatus = isReusableSize ? 'WASTE' : 'SCRAP';
      
      if (wastePiece.status !== expectedStatus) {
        throw new Error(`Waste piece classification incorrect: expected ${expectedStatus}, got ${wastePiece.status}`);
      }
      
      console.log(`  - Waste piece dimensions: ${wastePiece.length}×${wastePiece.width} ${wastePiece.unit}`);
      console.log(`  - Minimum required: ${minDimensions.length}×${minDimensions.width} ${wastePiece.unit}`);
      console.log(`  - Classification: ${wastePiece.status} (✓ Correct)`);
    }
    
    console.log('✓ Step 4: Test source piece status updates');
    const sourceUpdates = cuttingResult.sourcePieceUpdates;
    
    if (!sourceUpdates || !sourceUpdates.newStatus) {
      throw new Error('Source piece status updates missing');
    }
    
    console.log(`  - Original status: ${sourcePiece.status}`);
    console.log(`  - New status: ${sourceUpdates.newStatus}`);
    console.log(`  - New usable dimensions: ${sourceUpdates.newUsableLength}×${sourceUpdates.newUsableWidth}`);
    
    // Validate status update logic
    const sourceArea = sourcePiece.length * sourcePiece.width;
    const cutArea = cuttingResult.cutCalculations.cutArea;
    const remainingArea = sourceArea - cutArea;
    
    if (remainingArea < 0.001) {
      // Full consumption should result in SCRAP status
      if (sourceUpdates.newStatus !== 'SCRAP') {
        throw new Error(`Expected SCRAP status for full consumption, got ${sourceUpdates.newStatus}`);
      }
    } else if (cuttingResult.remainingPiece) {
      // If remaining piece created, source should be SCRAP
      if (sourceUpdates.newStatus !== 'SCRAP') {
        throw new Error(`Expected SCRAP status when remaining piece created, got ${sourceUpdates.newStatus}`);
      }
    }
    
    console.log(`  - Status update logic: ✓ Valid`);
    
    return {
      success: true,
      cuttingResult: cuttingResult,
      wasteGenerated: cuttingResult.newWastePieces.length > 0,
      traceabilityValid: true,
      classificationValid: true,
      statusUpdateValid: true
    };
    
  } catch (error) {
    console.error('✗ Waste management workflow failed:', error.message);
    return { success: false, error: error.message };
  }
}

/**
 * Test scrap dimension tracking and write-off
 */
function testScrapDimensionTracking() {
  console.log('\n=== Testing Scrap Dimension Tracking ===');
  
  try {
    // Test scenario where cutting creates scrap (very small remainder)
    const sourcePiece = {
      id: 2,
      product_id: 1,
      grn_item_id: 1,
      piece_number: 2,
      length: 105,
      width: 85,
      unit: 'cm',
      status: 'FULL',
      cost_per_area: 0.5,
      supplier_batch: 'BATCH001',
      quality_grade: 'A'
    };
    
    const cuttingData = {
      production_order_id: 1,
      bom_item_id: 1,
      cut_length: 100,
      cut_width: 80,
      unit: 'cm',
      operator_id: 1,
      notes: 'Scrap generation test'
    };
    
    console.log('✓ Processing cutting operation that generates scrap');
    const cuttingResult = cuttingOperationsService.processCuttingOperation(
      cuttingData,
      sourcePiece,
      { generateWastePieces: true, autoClassifyWaste: true }
    );
    
    if (!cuttingResult.isValid) {
      throw new Error(`Cutting operation failed: ${cuttingResult.error}`);
    }
    
    console.log(`  - Source dimensions: ${sourcePiece.length}×${sourcePiece.width} ${sourcePiece.unit}`);
    console.log(`  - Cut dimensions: ${cuttingData.cut_length}×${cuttingData.cut_width} ${cuttingData.unit}`);
    console.log(`  - Remaining area: ${cuttingResult.cutCalculations.remainingArea} cm²`);
    
    // Check if scrap dimensions are tracked
    if (cuttingResult.cutCalculations.scrapDimensions) {
      console.log('✓ Scrap dimensions tracked:');
      console.log(`  - Scrap dimensions: ${cuttingResult.cutCalculations.scrapDimensions.length}×${cuttingResult.cutCalculations.scrapDimensions.width} ${cuttingResult.cutCalculations.scrapDimensions.unit}`);
      console.log(`  - Scrap area: ${cuttingResult.cutCalculations.scrapDimensions.area} cm²`);
      
      // Validate scrap dimensions are below minimum reusable threshold
      const minDimensions = cuttingOperationsService.MIN_REUSABLE_DIMENSIONS[cuttingResult.cutCalculations.scrapDimensions.unit];
      const isBelowThreshold = cuttingResult.cutCalculations.scrapDimensions.length < minDimensions.length || 
                              cuttingResult.cutCalculations.scrapDimensions.width < minDimensions.width;
      
      if (!isBelowThreshold) {
        throw new Error('Scrap dimensions are above reusable threshold - should be classified as waste');
      }
      
      console.log(`  - Below reusable threshold: ✓ Valid`);
    }
    
    // Check waste pieces classification
    if (cuttingResult.newWastePieces && cuttingResult.newWastePieces.length > 0) {
      console.log('✓ Waste pieces generated:');
      cuttingResult.newWastePieces.forEach((waste, index) => {
        console.log(`  ${index + 1}. ${waste.length}×${waste.width} ${waste.unit} (${waste.status})`);
        
        // Validate SCRAP pieces are properly classified
        if (waste.status === 'SCRAP') {
          const minDimensions = cuttingOperationsService.MIN_REUSABLE_DIMENSIONS[waste.unit];
          const isBelowThreshold = waste.length < minDimensions.length || waste.width < minDimensions.width;
          
          if (!isBelowThreshold) {
            throw new Error(`Piece classified as SCRAP but dimensions are above threshold: ${waste.length}×${waste.width}`);
          }
          
          console.log(`     - SCRAP classification: ✓ Valid (below ${minDimensions.length}×${minDimensions.width} threshold)`);
        }
      });
    }
    
    return {
      success: true,
      scrapTracked: !!cuttingResult.cutCalculations.scrapDimensions,
      wasteClassificationValid: true,
      scrapDimensions: cuttingResult.cutCalculations.scrapDimensions
    };
    
  } catch (error) {
    console.error('✗ Scrap dimension tracking failed:', error.message);
    return { success: false, error: error.message };
  }
}

/**
 * Test waste reuse suggestions integration
 */
function testWasteReuseSuggestionsIntegration() {
  console.log('\n=== Testing Waste Reuse Suggestions Integration ===');
  
  try {
    // Mock scenario with existing waste pieces and new production order
    const mockWastePieces = [
      {
        id: 101,
        product_id: 1,
        piece_number: 101,
        length: 150,
        width: 120,
        unit: 'cm',
        status: 'WASTE',
        usable_length: 140,
        usable_width: 110,
        cost_per_area: 0.5,
        created_at: new Date('2024-01-01'),
        parent_piece_id: 1,
        created_from_cutting: true,
        product: {
          id: 1,
          name: 'Cotton Fabric',
          sku: 'CF001'
        }
      },
      {
        id: 102,
        product_id: 1,
        piece_number: 102,
        length: 80,
        width: 70,
        unit: 'cm',
        status: 'WASTE',
        usable_length: 75,
        usable_width: 65,
        cost_per_area: 0.5,
        created_at: new Date('2024-01-02'),
        parent_piece_id: 2,
        created_from_cutting: true,
        product: {
          id: 1,
          name: 'Cotton Fabric',
          sku: 'CF001'
        }
      }
    ];
    
    const bomRequirement = {
      id: 1,
      rm_product_id: 1,
      use_dimensions: true,
      required_length: 100,
      required_width: 80,
      dimension_unit: 'cm',
      rawMaterial: {
        id: 1,
        name: 'Cotton Fabric',
        sku: 'CF001'
      }
    };
    
    console.log('✓ Analyzing waste pieces for BOM requirements');
    console.log(`  - BOM requirement: ${bomRequirement.required_length}×${bomRequirement.required_width} ${bomRequirement.dimension_unit}`);
    console.log(`  - Available waste pieces: ${mockWastePieces.length}`);
    
    const suitableWastePieces = [];
    
    for (const wastePiece of mockWastePieces) {
      const wasteDimensions = {
        length: wastePiece.usable_length || wastePiece.length,
        width: wastePiece.usable_width || wastePiece.width,
        unit: wastePiece.unit
      };
      
      const requiredDimensions = {
        length: bomRequirement.required_length,
        width: bomRequirement.required_width,
        unit: bomRequirement.dimension_unit
      };
      
      // Check if waste piece can fit the requirement
      const canFit = wasteDimensions.length >= requiredDimensions.length && 
                    wasteDimensions.width >= requiredDimensions.width;
      
      if (canFit) {
        const unitsFromWaste = Math.floor(Math.min(
          wasteDimensions.length / requiredDimensions.length,
          wasteDimensions.width / requiredDimensions.width
        ));
        
        if (unitsFromWaste > 0) {
          const wasteArea = wasteDimensions.length * wasteDimensions.width;
          const requiredArea = requiredDimensions.length * requiredDimensions.width;
          const utilizationRatio = (requiredArea * unitsFromWaste) / wasteArea;
          const costSavings = wastePiece.cost_per_area * requiredArea * unitsFromWaste;
          
          suitableWastePieces.push({
            piece: wastePiece,
            unitsAvailable: unitsFromWaste,
            wasteArea: wasteArea,
            requiredArea: requiredArea,
            utilizationRatio: utilizationRatio,
            costSavings: costSavings
          });
          
          console.log(`    ✓ Piece ${wastePiece.piece_number}: ${wasteDimensions.length}×${wasteDimensions.width} → ${unitsFromWaste} units (${(utilizationRatio * 100).toFixed(1)}% utilization)`);
        }
      } else {
        console.log(`    ✗ Piece ${wastePiece.piece_number}: ${wasteDimensions.length}×${wasteDimensions.width} → insufficient size`);
      }
    }
    
    console.log('✓ Waste reuse analysis results:');
    console.log(`  - Suitable waste pieces: ${suitableWastePieces.length}/${mockWastePieces.length}`);
    
    if (suitableWastePieces.length > 0) {
      // Sort by utilization ratio (highest first)
      suitableWastePieces.sort((a, b) => b.utilizationRatio - a.utilizationRatio);
      
      const totalCostSavings = suitableWastePieces.reduce((sum, piece) => sum + piece.costSavings, 0);
      const bestUtilization = suitableWastePieces[0].utilizationRatio;
      
      console.log(`  - Total potential cost savings: $${totalCostSavings.toFixed(2)}`);
      console.log(`  - Best utilization ratio: ${(bestUtilization * 100).toFixed(1)}%`);
      console.log(`  - Recommendation: Use waste pieces for cost-effective production`);
      
      // Validate waste piece properties for reuse
      for (const suitablePiece of suitableWastePieces) {
        const waste = suitablePiece.piece;
        
        // Validate traceability
        if (!waste.parent_piece_id || !waste.created_from_cutting) {
          throw new Error(`Waste piece ${waste.piece_number} missing traceability information`);
        }
        
        // Validate status
        if (waste.status !== 'WASTE') {
          throw new Error(`Waste piece ${waste.piece_number} has incorrect status: ${waste.status}`);
        }
        
        console.log(`    ✓ Piece ${waste.piece_number} validated for reuse`);
      }
    } else {
      console.log(`  - No suitable waste pieces found for this requirement`);
    }
    
    return {
      success: true,
      totalWastePieces: mockWastePieces.length,
      suitableWastePieces: suitableWastePieces.length,
      wasteReusePossible: suitableWastePieces.length > 0,
      traceabilityValid: true
    };
    
  } catch (error) {
    console.error('✗ Waste reuse suggestions integration failed:', error.message);
    return { success: false, error: error.message };
  }
}

/**
 * Run all waste and scrap management integration tests
 */
function runWasteScrapManagementTests() {
  console.log('🧪 WASTE AND SCRAP MANAGEMENT INTEGRATION TESTS');
  console.log('================================================');
  
  const results = {
    wasteWorkflow: testCompleteWasteManagementWorkflow(),
    scrapTracking: testScrapDimensionTracking(),
    wasteReuseSuggestions: testWasteReuseSuggestionsIntegration()
  };
  
  // 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 waste and scrap management tests passed!');
    console.log('\nValidated Requirements:');
    console.log('✓ 4.3: System creates new waste pieces with status WASTE');
    console.log('✓ 4.4: System marks dimensions as SCRAP when too small');
    console.log('✓ 5.3: System suggests available waste pieces for production planning');
    console.log('\nKey Features Validated:');
    console.log('✓ Complete waste generation workflow with traceability');
    console.log('✓ Proper waste piece classification (WASTE vs SCRAP)');
    console.log('✓ Source piece status updates after cutting');
    console.log('✓ Scrap dimension tracking and write-off capability');
    console.log('✓ Waste reuse suggestions with cost savings calculation');
    console.log('✓ Integration with production planning workflow');
  } 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) {
  runWasteScrapManagementTests();
}

module.exports = {
  runWasteScrapManagementTests,
  testCompleteWasteManagementWorkflow,
  testScrapDimensionTracking,
  testWasteReuseSuggestionsIntegration
};