import MarginCalculator from "../../src/utils/marginCalculator.js";

describe("Margin Calculator (Unit Tests)", () => {
  describe("Fee Calculations", () => {
    it("should calculate standard fee based on percentage and fixed fee", () => {
      const fee = MarginCalculator.calculateFee(1000, 0.01, 5); // 1% of 1000 = 10 + 5 = 15
      expect(fee).toBe(15);
    });

    it("should respect the minCap", () => {
      const fee = MarginCalculator.calculateFee(100, 0.01, 1, 5, 50); // 1% of 100 = 1 + 1 = 2 (below minCap of 5)
      expect(fee).toBe(5);
    });

    it("should respect the maxCap", () => {
      const fee = MarginCalculator.calculateFee(10000, 0.05, 10, 5, 100); // 5% of 10000 = 500 + 10 = 510 (above maxCap of 100)
      expect(fee).toBe(100);
    });
  });

  describe("Pricing Margin", () => {
    const pricingConfig = {
      providerPercentage: 0.005, // 0.5%
      providerFixedFee: 2,
      providerMinCap: 5,
      providerMaxCap: 50,
      customerPercentage: 0.02, // 2%
      customerFixedFee: 10,
      customerMinCap: 15,
      customerMaxCap: 200,
    };

    it("should calculate provider fee, customer fee, and platform profit", () => {
      const result = MarginCalculator.calculatePricingMargin(1000, pricingConfig);
      // Provider fee: 1000 * 0.005 = 5 + 2 = 7
      // Customer fee: 1000 * 0.02 = 20 + 10 = 30
      // Profit: 30 - 7 = 23
      expect(result.providerFee).toBe(7);
      expect(result.customerFee).toBe(30);
      expect(result.profit).toBe(23);
    });

    it("should return 0 fees and profit if config is missing", () => {
      const result = MarginCalculator.calculatePricingMargin(1000, null);
      expect(result.providerFee).toBe(0);
      expect(result.customerFee).toBe(0);
      expect(result.profit).toBe(0);
    });
  });

  describe("FX Margin and Conversions", () => {
    it("should calculate platform rate and profit when adding margin", () => {
      const exchangeRateConfig = {
        rate: 0,
        margin: 10,
        marginOperation: "add", // e.g. NGN per USD (we charge the user more NGN)
      };

      const result = MarginCalculator.calculateFxMargin(100, exchangeRateConfig, 1600);
      // Live rate: 1600. Margin: +10. Platform Rate = 1610
      // Converted amount (cost to user in base currency): 100 * 1610 = 161,000
      // Margin profit: 100 * (1610 - 1600) = 1000
      expect(result.platformRate).toBe(1610);
      expect(result.convertedAmount).toBe(161000);
      expect(result.marginProfit).toBe(1000);
    });

    it("should calculate platform rate and profit when subtracting margin", () => {
      const exchangeRateConfig = {
        rate: 0,
        margin: 15,
        marginOperation: "subtract", // e.g. NGN per USD (user gets less target currency)
      };

      const result = MarginCalculator.calculateFxMargin(100, exchangeRateConfig, 1600);
      // Live rate: 1600. Margin: -15. Platform Rate = 1585
      // Converted amount: 100 * 1585 = 158,500
      // Margin profit: 100 * (1600 - 1585) = 1500
      expect(result.platformRate).toBe(1585);
      expect(result.convertedAmount).toBe(158500);
      expect(result.marginProfit).toBe(1500);
    });

    it("should respect fixed rate from database config", () => {
      const exchangeRateConfig = {
        rate: 1650, // Fixed rate
        margin: 10,
        marginOperation: "add",
      };

      const result = MarginCalculator.calculateFxMargin(100, exchangeRateConfig, 1600);
      // Fixed rate takes precedence: Platform Rate = 1650
      // Converted amount: 100 * 1650 = 165,000
      // Margin profit: 100 * (1650 - 1600) = 5000
      expect(result.platformRate).toBe(1650);
      expect(result.convertedAmount).toBe(165000);
      expect(result.marginProfit).toBe(5000);
    });
  });
});
