/**
 * Test file to verify discount calculation logic for orders
 * 
 * This test verifies:
 * 1. Products added via "Add Another Product" with price > 0 should NOT appear in discount
 * 2. Products added via "Add a free product" (amountPerTub = 0) should be excluded from productsSubtotal
 * 3. Discount should only show when there's a manual override or actual difference
 */

interface MockOrderItem {
  id: number;
  orderId: number;
  productId: number;
  product: {
    id: number;
    name: string;
    amount: string | number;
  };
  count: number;
  amountPerTub: number;
  totalAmount: number;
  postageServiceChargeId?: number;
  postageServiceCharge?: {
    id: number;
    name: string;
    amount: number;
  };
  deductionNote?: string;
}

interface MockOrder {
  id: number;
  orderNumber: string;
  customerId: number;
  orderItems: MockOrderItem[];
}

/**
 * Calculate products subtotal excluding free products (amountPerTub = 0)
 * This mimics the logic in ordersAndNotes.tsx and CustomerOrdersDialog.tsx
 */
function calculateProductsSubtotal(orderItems: MockOrderItem[]): number {
  let productsSubtotal = 0;
  
  orderItems.forEach((item) => {
    const amountPerTub = Number(item.amountPerTub) || 0;
    // Exclude free products (amountPerTub = 0) from products subtotal
    // Free products should only be added via "Add a free product" button
    if (amountPerTub > 0) {
      const itemSubtotal = amountPerTub * item.count;
      productsSubtotal += itemSubtotal;
    }
  });
  
  return productsSubtotal;
}

/**
 * Calculate discount amount
 * This mimics the logic in ordersAndNotes.tsx and CustomerOrdersDialog.tsx
 */
function calculateDiscount(orderItems: MockOrderItem[]): {
  productsSubtotal: number;
  postageAmount: number;
  orderTotal: number;
  firstItemTotal: number | null;
  discountAmount: number;
} {
  const productsSubtotal = calculateProductsSubtotal(orderItems);
  
  // Get postage from first item
  const postageAmount = orderItems[0]?.postageServiceCharge
    ? Number(orderItems[0].postageServiceCharge.amount) || 0
    : 0;
  
  // Calculate order total (products + postage)
  const orderTotal = productsSubtotal + postageAmount;
  
  // Get the actual order total by summing all items' totalAmount
  // This accounts for all products including any manual adjustments
  const actualOrderTotal = orderItems.reduce((sum, item) => {
    const itemTotal = item.totalAmount ? Number(item.totalAmount) : 0;
    return sum + itemTotal;
  }, 0);
  
  // Calculate discount amount if there's a difference
  // Discount = actual total - calculated total (products + postage, excluding free products)
  const discountAmount = actualOrderTotal !== orderTotal
    ? actualOrderTotal - orderTotal
    : 0;
  
  return {
    productsSubtotal,
    postageAmount,
    orderTotal,
    actualOrderTotal,
    discountAmount,
  };
}

// Test Case 1: Product added via "Add Another Product" with price > 0 should NOT appear in discount
function testRegularProductNotInDiscount() {
  console.log("\nTest 1: Regular product (added via 'Add Another Product') should NOT appear in discount");
  
  const order: MockOrder = {
    id: 1,
    orderNumber: "ORD-001",
    customerId: 1,
    orderItems: [
      {
        id: 1,
        orderId: 1,
        productId: 1,
        product: { id: 1, name: "test3", amount: 20 },
        count: 2,
        amountPerTub: 20, // Regular product with price > 0
        totalAmount: 60, // 40 (products) + 20 (postage)
        postageServiceChargeId: 1,
        postageServiceCharge: { id: 1, name: "Standard", amount: 20 },
      },
      {
        id: 2,
        orderId: 1,
        productId: 2,
        product: { id: 2, name: "test2", amount: 30 },
        count: 2,
        amountPerTub: 30, // Regular product with price > 0 (added via "Add Another Product")
        totalAmount: 60, // 60 (products only, no postage)
      },
    ],
  };
  
  const result = calculateDiscount(order.orderItems);
  
  console.log("Order items:", order.orderItems.map(item => ({
    product: item.product.name,
    amountPerTub: item.amountPerTub,
    count: item.count,
    totalAmount: item.totalAmount,
  })));
  console.log("Products subtotal:", result.productsSubtotal);
  console.log("Postage:", result.postageAmount);
  console.log("Calculated order total:", result.orderTotal);
  console.log("Actual order total (sum of all totalAmounts):", result.actualOrderTotal);
  console.log("Discount amount:", result.discountAmount);
  
  // Expected: productsSubtotal = 20*2 + 30*2 = 100
  // Expected: orderTotal = 100 + 20 = 120
  // Expected: firstItemTotal = 60 (from first item)
  // But wait, the totalAmount in the first item includes postage, so we need to check the sum of all totalAmounts
  const sumOfTotalAmounts = order.orderItems.reduce((sum, item) => sum + item.totalAmount, 0);
  console.log("Sum of all totalAmounts:", sumOfTotalAmounts);
  
  // The discount should be: sumOfTotalAmounts - orderTotal = 120 - 120 = 0
  const expectedDiscount = sumOfTotalAmounts - result.orderTotal;
  const passed = Math.abs(result.discountAmount - expectedDiscount) < 0.01;
  
  console.log(`Expected discount: ${expectedDiscount}, Got: ${result.discountAmount}, Pass: ${passed}`);
  
  return passed;
}

// Test Case 2: Free product (amountPerTub = 0) should be excluded from productsSubtotal
function testFreeProductExcludedFromSubtotal() {
  console.log("\nTest 2: Free product (amountPerTub = 0) should be excluded from productsSubtotal");
  
  const order: MockOrder = {
    id: 2,
    orderNumber: "ORD-002",
    customerId: 1,
    orderItems: [
      {
        id: 3,
        orderId: 2,
        productId: 1,
        product: { id: 1, name: "test3", amount: 20 },
        count: 2,
        amountPerTub: 20, // Regular product
        totalAmount: 60, // 40 (products) + 20 (postage)
        postageServiceChargeId: 1,
        postageServiceCharge: { id: 1, name: "Standard", amount: 20 },
      },
      {
        id: 4,
        orderId: 2,
        productId: 1,
        product: { id: 1, name: "test3", amount: 20 },
        count: 2,
        amountPerTub: 0, // Free product (added via "Add a free product")
        totalAmount: 0, // Free products have totalAmount = 0
      },
    ],
  };
  
  const result = calculateDiscount(order.orderItems);
  
  console.log("Order items:", order.orderItems.map(item => ({
    product: item.product.name,
    amountPerTub: item.amountPerTub,
    count: item.count,
    totalAmount: item.totalAmount,
    isFree: item.amountPerTub === 0,
  })));
  console.log("Products subtotal:", result.productsSubtotal);
  console.log("Postage:", result.postageAmount);
  console.log("Calculated order total:", result.orderTotal);
  
  // Expected: productsSubtotal = 20*2 = 40 (free product excluded)
  // Expected: orderTotal = 40 + 20 = 60
  const expectedSubtotal = 40;
  const expectedOrderTotal = 60;
  
  const subtotalPass = Math.abs(result.productsSubtotal - expectedSubtotal) < 0.01;
  const orderTotalPass = Math.abs(result.orderTotal - expectedOrderTotal) < 0.01;
  
  console.log(`Expected subtotal: ${expectedSubtotal}, Got: ${result.productsSubtotal}, Pass: ${subtotalPass}`);
  console.log(`Expected order total: ${expectedOrderTotal}, Got: ${result.orderTotal}, Pass: ${orderTotalPass}`);
  
  return subtotalPass && orderTotalPass;
}

// Test Case 3: Scenario from user's issue - test2 added via "Add Another Product" should NOT show in discount
function testUserIssueScenario() {
  console.log("\nTest 3: User issue scenario - test2 added via 'Add Another Product' should NOT show in discount");
  
  // This simulates the scenario from the user:
  // - test3: 2 qty @ £20 = £40 (regular product)
  // - test2: 2 qty @ £30 = £60 (added via "Add Another Product", should NOT be in discount)
  // - Postage: £20
  // - Expected total: £120
  // - If test2 was incorrectly included in discount, discount would show -£60
  
  const order: MockOrder = {
    id: 3,
    orderNumber: "ORD-003",
    customerId: 1,
    orderItems: [
      {
        id: 5,
        orderId: 3,
        productId: 1,
        product: { id: 1, name: "test3", amount: 20 },
        count: 2,
        amountPerTub: 20,
        totalAmount: 60, // 40 (products) + 20 (postage)
        postageServiceChargeId: 1,
        postageServiceCharge: { id: 1, name: "Standard", amount: 20 },
      },
      {
        id: 6,
        orderId: 3,
        productId: 2,
        product: { id: 2, name: "test2", amount: 30 },
        count: 2,
        amountPerTub: 30, // Regular product added via "Add Another Product"
        totalAmount: 60, // 60 (products only)
      },
    ],
  };
  
  const result = calculateDiscount(order.orderItems);
  const sumOfTotalAmounts = order.orderItems.reduce((sum, item) => sum + item.totalAmount, 0);
  
  console.log("Order items:", order.orderItems.map(item => ({
    product: item.product.name,
    amountPerTub: item.amountPerTub,
    count: item.count,
    totalAmount: item.totalAmount,
  })));
  console.log("Products subtotal (excluding free products):", result.productsSubtotal);
  console.log("Postage:", result.postageAmount);
  console.log("Calculated order total:", result.orderTotal);
  console.log("Sum of all totalAmounts:", sumOfTotalAmounts);
  console.log("Discount amount:", result.discountAmount);
  
  // Expected: productsSubtotal = 20*2 + 30*2 = 100
  // Expected: orderTotal = 100 + 20 = 120
  // Expected: sumOfTotalAmounts = 60 + 60 = 120
  // Expected: discount = 120 - 120 = 0 (NO discount should appear)
  
  const expectedSubtotal = 100;
  const expectedOrderTotal = 120;
  const expectedDiscount = 0;
  
  const subtotalPass = Math.abs(result.productsSubtotal - expectedSubtotal) < 0.01;
  const orderTotalPass = Math.abs(result.orderTotal - expectedOrderTotal) < 0.01;
  const discountPass = Math.abs(result.discountAmount - expectedDiscount) < 0.01;
  
  console.log(`Expected subtotal: ${expectedSubtotal}, Got: ${result.productsSubtotal}, Pass: ${subtotalPass}`);
  console.log(`Expected order total: ${expectedOrderTotal}, Got: ${result.orderTotal}, Pass: ${orderTotalPass}`);
  console.log(`Expected discount: ${expectedDiscount}, Got: ${result.discountAmount}, Pass: ${discountPass}`);
  console.log(`\n✓ test2 (added via 'Add Another Product') is correctly NOT showing in discount`);
  
  return subtotalPass && orderTotalPass && discountPass;
}

// Test Case 4: Free product should only affect discount if order total is manually overridden
function testFreeProductWithManualOverride() {
  console.log("\nTest 4: Free product with manual order total override");
  
  const order: MockOrder = {
    id: 4,
    orderNumber: "ORD-004",
    customerId: 1,
    orderItems: [
      {
        id: 7,
        orderId: 4,
        productId: 1,
        product: { id: 1, name: "test3", amount: 20 },
        count: 2,
        amountPerTub: 20,
        totalAmount: 50, // Manually overridden (should be 60, but set to 50)
        postageServiceChargeId: 1,
        postageServiceCharge: { id: 1, name: "Standard", amount: 20 },
        deductionNote: "Manual discount applied",
      },
      {
        id: 8,
        orderId: 4,
        productId: 1,
        product: { id: 1, name: "test3", amount: 20 },
        count: 1,
        amountPerTub: 0, // Free product
        totalAmount: 0,
      },
    ],
  };
  
  const result = calculateDiscount(order.orderItems);
  const sumOfTotalAmounts = order.orderItems.reduce((sum, item) => sum + item.totalAmount, 0);
  
  console.log("Order items:", order.orderItems.map(item => ({
    product: item.product.name,
    amountPerTub: item.amountPerTub,
    count: item.count,
    totalAmount: item.totalAmount,
  })));
  console.log("Products subtotal (excluding free products):", result.productsSubtotal);
  console.log("Postage:", result.postageAmount);
  console.log("Calculated order total:", result.orderTotal);
  console.log("Sum of all totalAmounts:", sumOfTotalAmounts);
  console.log("Discount amount:", result.discountAmount);
  
  // Expected: productsSubtotal = 20*2 = 40 (free product excluded)
  // Expected: orderTotal = 40 + 20 = 60
  // Expected: sumOfTotalAmounts = 50 + 0 = 50
  // Expected: discount = 50 - 60 = -10 (discount of £10)
  
  const expectedSubtotal = 40;
  const expectedOrderTotal = 60;
  const expectedDiscount = -10; // Negative because total is less than calculated
  
  const subtotalPass = Math.abs(result.productsSubtotal - expectedSubtotal) < 0.01;
  const orderTotalPass = Math.abs(result.orderTotal - expectedOrderTotal) < 0.01;
  const discountPass = Math.abs(result.discountAmount - expectedDiscount) < 0.01;
  
  console.log(`Expected subtotal: ${expectedSubtotal}, Got: ${result.productsSubtotal}, Pass: ${subtotalPass}`);
  console.log(`Expected order total: ${expectedOrderTotal}, Got: ${result.orderTotal}, Pass: ${orderTotalPass}`);
  console.log(`Expected discount: ${expectedDiscount}, Got: ${result.discountAmount}, Pass: ${discountPass}`);
  
  return subtotalPass && orderTotalPass && discountPass;
}

// Run all tests
function runAllTests() {
  console.log("=".repeat(60));
  console.log("DISCOUNT CALCULATION TESTS");
  console.log("=".repeat(60));
  
  const results = {
    test1: testRegularProductNotInDiscount(),
    test2: testFreeProductExcludedFromSubtotal(),
    test3: testUserIssueScenario(),
    test4: testFreeProductWithManualOverride(),
  };
  
  console.log("\n" + "=".repeat(60));
  console.log("TEST RESULTS");
  console.log("=".repeat(60));
  console.log("Test 1 (Regular Product Not In Discount):", results.test1 ? "✓ PASS" : "✗ FAIL");
  console.log("Test 2 (Free Product Excluded From Subtotal):", results.test2 ? "✓ PASS" : "✗ FAIL");
  console.log("Test 3 (User Issue Scenario):", results.test3 ? "✓ PASS" : "✗ FAIL");
  console.log("Test 4 (Free Product With Manual Override):", results.test4 ? "✓ PASS" : "✗ FAIL");
  
  const allPassed = Object.values(results).every(r => r === true);
  console.log("\nOverall:", allPassed ? "✓ ALL TESTS PASSED" : "✗ SOME TESTS FAILED");
  
  return results;
}

// Export for use
if (typeof module !== 'undefined' && module.exports) {
  module.exports = { 
    runAllTests, 
    calculateProductsSubtotal, 
    calculateDiscount,
    testRegularProductNotInDiscount,
    testFreeProductExcludedFromSubtotal,
    testUserIssueScenario,
    testFreeProductWithManualOverride,
  };
}

// Run if executed directly
if (typeof window === 'undefined') {
  runAllTests();
}

