/**
 * Checkout Pricing Tests
 *
 * These tests verify that the checkout flow uses correct pricing:
 * - Correct Stripe price IDs are selected
 * - Yearly billing uses discounted prices
 * - Price lookup returns valid Stripe price IDs
 */

import { getStripePriceId } from "@/lib/stripe-prices";

// GBP to QAR rate
const GBP_TO_QAR_RATE = 4.62;

// Expected tier prices in GBP (from pricing-tiers.ts)
const TIER_PRICES_GBP = {
  tier1: 179,
  tier2: 209,
  tier3: 249,
  tier4: 349,
  tier5: 449,
};

describe("Checkout Price Selection", () => {
  describe("getStripePriceId", () => {
    it("should return monthly price ID for tier1 monthly", async () => {
      const priceId = await getStripePriceId("tier1", "monthly", "QAR");
      expect(priceId).toBeDefined();
      expect(priceId).toMatch(/^price_/);
    });

    it("should return yearly price ID for tier1 yearly", async () => {
      const priceId = await getStripePriceId("tier1", "yearly", "QAR");
      expect(priceId).toBeDefined();
      expect(priceId).toMatch(/^price_/);
    });

    it("should return different price IDs for monthly vs yearly", async () => {
      const monthlyId = await getStripePriceId("tier2", "monthly", "QAR");
      const yearlyId = await getStripePriceId("tier2", "yearly", "QAR");

      expect(monthlyId).not.toBe(yearlyId);
    });

    it("should return price IDs for all tiers", async () => {
      const tiers = ["tier1", "tier2", "tier3", "tier4", "tier5"];

      for (const tier of tiers) {
        const monthlyId = await getStripePriceId(tier, "monthly", "QAR");
        const yearlyId = await getStripePriceId(tier, "yearly", "QAR");

        expect(monthlyId).toBeDefined();
        expect(yearlyId).toBeDefined();
        expect(monthlyId).toMatch(/^price_/);
        expect(yearlyId).toMatch(/^price_/);
      }
    });

    it("should return null for invalid tier", async () => {
      const priceId = await getStripePriceId("invalid_tier", "monthly", "QAR");
      expect(priceId).toBeNull();
    });
  });
});

describe("Yearly Price Verification", () => {
  /**
   * These tests verify the yearly prices match expected calculations
   * Formula: (GBP × 4.62) × 12 × 0.93
   */

  const expectedYearlyPricesQAR = {
    tier1: 9229, // 179 × 4.62 × 12 × 0.93 ≈ 9,229 QAR
    tier2: 10776, // 209 × 4.62 × 12 × 0.93 ≈ 10,776 QAR
    tier3: 12838, // 249 × 4.62 × 12 × 0.93 ≈ 12,838 QAR
    tier4: 17994, // 349 × 4.62 × 12 × 0.93 ≈ 17,994 QAR
    tier5: 23150, // 449 × 4.62 × 12 × 0.93 ≈ 23,150 QAR
  };

  it("should have tier5 yearly price around 23,150 QAR (not 5,016 QAR)", () => {
    // This is the critical test - tier5 was previously charging ~5,016 QAR
    // which was incorrect. It should be ~23,150 QAR
    const monthlyGbp = TIER_PRICES_GBP.tier5;
    const monthlyQar = Math.round(monthlyGbp * GBP_TO_QAR_RATE);
    const yearlyQar = Math.round(monthlyQar * 12 * 0.93);

    expect(yearlyQar).toBeGreaterThan(23000);
    expect(yearlyQar).toBeLessThan(23300);

    // Ensure it's NOT the old incorrect value
    expect(yearlyQar).not.toBeCloseTo(5016, -2);
  });

  Object.entries(expectedYearlyPricesQAR).forEach(
    ([tierId, expectedYearly]) => {
      it(`should have correct yearly price for ${tierId}: ~${expectedYearly} QAR`, () => {
        const monthlyGbp =
          TIER_PRICES_GBP[tierId as keyof typeof TIER_PRICES_GBP];
        const monthlyQar = Math.round(monthlyGbp * GBP_TO_QAR_RATE);
        const calculatedYearly = Math.round(monthlyQar * 12 * 0.93);

        // Allow 1% tolerance for rounding
        const tolerance = expectedYearly * 0.01;
        expect(calculatedYearly).toBeGreaterThan(expectedYearly - tolerance);
        expect(calculatedYearly).toBeLessThan(expectedYearly + tolerance);
      });
    },
  );
});

describe("Monthly Equivalent Display Values", () => {
  /**
   * These are the "per month" values shown on pricing pages
   * when yearly billing is selected
   */

  const expectedMonthlyEquivalentsQAR = {
    tier1: 769, // 827 × 0.93 ≈ 769 QAR/month
    tier2: 898, // 966 × 0.93 ≈ 898 QAR/month
    tier3: 1070, // 1150 × 0.93 ≈ 1070 QAR/month
    tier4: 1499, // 1612 × 0.93 ≈ 1499 QAR/month
    tier5: 1929, // 2074 × 0.93 ≈ 1929 QAR/month
  };

  Object.entries(expectedMonthlyEquivalentsQAR).forEach(
    ([tierId, expectedMonthly]) => {
      it(`should show correct monthly equivalent for ${tierId}: ~${expectedMonthly} QAR/mo`, () => {
        const monthlyGbp =
          TIER_PRICES_GBP[tierId as keyof typeof TIER_PRICES_GBP];
        const monthlyQar = Math.round(monthlyGbp * GBP_TO_QAR_RATE);
        const discountedMonthly = Math.round(monthlyQar * 0.93);

        // Allow small rounding difference
        expect(discountedMonthly).toBeGreaterThan(expectedMonthly - 5);
        expect(discountedMonthly).toBeLessThan(expectedMonthly + 5);
      });
    },
  );
});

describe("Billing Period Validation", () => {
  it('should accept "monthly" as valid billing period', async () => {
    const priceId = await getStripePriceId("tier1", "monthly", "QAR");
    expect(priceId).toBeDefined();
  });

  it('should accept "yearly" as valid billing period', async () => {
    const priceId = await getStripePriceId("tier1", "yearly", "QAR");
    expect(priceId).toBeDefined();
  });
});

describe("Currency Handling", () => {
  it("should return QAR prices for QAR currency", async () => {
    const priceId = await getStripePriceId("tier1", "monthly", "QAR");
    expect(priceId).toBeDefined();
  });

  it("should handle different currency codes", async () => {
    // Test with various currency codes the system might receive
    const currencies = ["QAR", "qar", "SAR", "AED"];

    for (const currency of currencies) {
      const priceId = await getStripePriceId("tier1", "monthly", currency);
      // Should return a price ID or null (not throw error)
      if (priceId) {
        expect(priceId).toMatch(/^price_/);
      }
    }
  });
});

describe("Regression Tests", () => {
  /**
   * These tests prevent specific bugs from recurring
   */

  it("should NOT use old incorrect tier5 yearly price (~5,016 QAR)", () => {
    // The old bug was using 449 directly as QAR instead of converting from GBP
    // 449 × 12 × 0.93 = 5,010.84 QAR (WRONG!)
    // Correct: (449 × 4.62) × 12 × 0.93 = 23,150 QAR

    const incorrectYearly = 449 * 12 * 0.93; // ~5,010 QAR
    const correctYearly = Math.round(449 * GBP_TO_QAR_RATE) * 12 * 0.93; // ~23,150 QAR

    // The correct yearly should be about 4.62x the incorrect value
    expect(correctYearly / incorrectYearly).toBeCloseTo(GBP_TO_QAR_RATE, 1);

    // Verify correct value is in expected range
    expect(correctYearly).toBeGreaterThan(23000);
    expect(correctYearly).toBeLessThan(23300);
  });

  it("should convert GBP to QAR before calculating yearly total", () => {
    const monthlyGbp = 449;
    const monthlyQar = Math.round(monthlyGbp * GBP_TO_QAR_RATE);

    // QAR monthly should be ~4.62x GBP monthly
    expect(monthlyQar / monthlyGbp).toBeCloseTo(GBP_TO_QAR_RATE, 1);

    // Yearly QAR should be ~4.62x what yearly GBP would be
    const yearlyGbp = monthlyGbp * 12 * 0.93;
    const yearlyQar = monthlyQar * 12 * 0.93;

    expect(yearlyQar / yearlyGbp).toBeCloseTo(GBP_TO_QAR_RATE, 1);
  });

  it("should apply 7% discount (not some other percentage)", () => {
    const monthly = 1000;
    const yearly = monthly * 12 * 0.93;
    const regularYearly = monthly * 12;
    const discount = ((regularYearly - yearly) / regularYearly) * 100;

    expect(discount).toBeCloseTo(7, 1);
  });
});
