/**
 * Smoke Tests for Critical Billing Paths
 * Quick validation that core billing functionality works
 * Run these before every deployment!
 */

import {
  calculateProratedUpgrade,
  calculateDowngradeCredit,
  shouldChargeSetupFee,
  convertPrice,
  getDaysUntilBilling,
} from "@/lib/utils/pricing-helpers";
import { PRICING_TIERS } from "@/lib/config/pricing-tiers";
import type { PricingTier } from "@/lib/types/pricing";

describe("Billing Critical Path Smoke Tests", () => {
  describe("🚨 CRITICAL: Proration Calculations", () => {
    it("[CRITICAL] Upgrade calculation must be accurate", () => {
      const result = calculateProratedUpgrade(966, 1200, 14, "monthly");
      expect(result).toBeCloseTo(109.2, 0);
    });

    it("[CRITICAL] Downgrade calculation must be accurate", () => {
      const result = calculateDowngradeCredit(966, 500, 14, "monthly");
      expect(result.creditAmount).toBeCloseTo(217.47, 0);
      expect(result.nextBillingCharge).toBeCloseTo(282.53, 0);
    });

    it("[CRITICAL] Must never return negative charges", () => {
      // Test upgrade
      const upgrade = calculateProratedUpgrade(1000, 500, 15, "monthly");
      expect(upgrade).toBeGreaterThanOrEqual(0);

      // Test downgrade
      const downgrade = calculateDowngradeCredit(1000, 500, 15, "monthly");
      expect(downgrade.nextBillingCharge).toBeGreaterThanOrEqual(0);
    });
  });

  describe("🚨 CRITICAL: Setup Fee Protection", () => {
    const tierWithFee: PricingTier = {
      id: "tier2",
      nameEn: "Pro",
      nameAr: "محترف",
      priceGBP: 299,
      setupGBP: 199,
      popular: true,
      featuresEn: [],
      featuresAr: [],
    };

    it("[CRITICAL] Must NOT charge setup fee if already paid", () => {
      const result = shouldChargeSetupFee(true, tierWithFee);
      expect(result).toBe(false); // ✅ PROTECTED
    });

    it("[CRITICAL] Must charge setup fee only on first subscription", () => {
      const result = shouldChargeSetupFee(false, tierWithFee);
      expect(result).toBe(true);
    });
  });

  describe("🚨 CRITICAL: Currency Conversion", () => {
    it("[CRITICAL] GCC currencies must convert correctly", () => {
      const testPrice = 100; // 100 GBP

      const qar = convertPrice(testPrice, "QAR");
      const sar = convertPrice(testPrice, "SAR");
      const aed = convertPrice(testPrice, "AED");

      expect(qar).toBe(462); // 100 * 4.62
      expect(sar).toBe(476); // 100 * 4.76
      expect(aed).toBe(466); // 100 * 4.66

      // All should be positive
      expect(qar).toBeGreaterThan(0);
      expect(sar).toBeGreaterThan(0);
      expect(aed).toBeGreaterThan(0);
    });

    it("[CRITICAL] GBP to GBP must be identity function", () => {
      const result = convertPrice(100, "GBP");
      expect(result).toBe(100);
    });
  });

  describe("🚨 CRITICAL: Date Calculations", () => {
    it("[CRITICAL] Days remaining must never be negative", () => {
      const pastDate = new Date(Date.now() - 5 * 24 * 60 * 60 * 1000);
      const result = getDaysUntilBilling(pastDate);
      expect(result).toBe(0); // Not negative!
    });

    it("[CRITICAL] Future dates must calculate correctly", () => {
      const futureDate = new Date(Date.now() + 14 * 24 * 60 * 60 * 1000);
      const result = getDaysUntilBilling(futureDate);
      expect(result).toBeGreaterThanOrEqual(13); // Allow for rounding
      expect(result).toBeLessThanOrEqual(15);
    });
  });

  describe("🚨 CRITICAL: Pricing Tiers Configuration", () => {
    it("[CRITICAL] All tiers must have required fields", () => {
      PRICING_TIERS.forEach((tier) => {
        expect(tier.id).toBeTruthy();
        expect(tier.nameEn).toBeTruthy();
        expect(tier.nameAr).toBeTruthy();
        expect(tier.priceGBP).toBeGreaterThan(0);
        expect(tier.setupGBP).toBeGreaterThanOrEqual(0);
        expect(Array.isArray(tier.featuresEn)).toBe(true);
        expect(Array.isArray(tier.featuresAr)).toBe(true);
      });
    });

    it("[CRITICAL] Tiers must be in ascending price order", () => {
      for (let i = 1; i < PRICING_TIERS.length; i++) {
        const prevPrice = PRICING_TIERS[i - 1].priceGBP;
        const currentPrice = PRICING_TIERS[i].priceGBP;

        expect(currentPrice).toBeGreaterThanOrEqual(prevPrice);
      }
    });

    it("[CRITICAL] All tier IDs must be unique", () => {
      const ids = PRICING_TIERS.map((t) => t.id);
      const uniqueIds = new Set(ids);

      expect(uniqueIds.size).toBe(PRICING_TIERS.length);
    });
  });

  describe("🚨 CRITICAL: Edge Cases", () => {
    it("[CRITICAL] Must handle 0 days remaining", () => {
      const upgrade = calculateProratedUpgrade(500, 1000, 0, "monthly");
      const downgrade = calculateDowngradeCredit(1000, 500, 0, "monthly");

      expect(upgrade).toBe(0);
      expect(downgrade.creditAmount).toBe(0);
      expect(downgrade.nextBillingCharge).toBe(500);
    });

    it("[CRITICAL] Must handle full month (30 days)", () => {
      const upgrade = calculateProratedUpgrade(500, 1000, 30, "monthly");
      const downgrade = calculateDowngradeCredit(1000, 500, 30, "monthly");

      expect(upgrade).toBeCloseTo(500, 0); // Full difference
      expect(downgrade.creditAmount).toBeCloseTo(500, 0);
    });

    it("[CRITICAL] Must handle same plan (no change)", () => {
      const result = calculateProratedUpgrade(500, 500, 15, "monthly");
      expect(result).toBe(0); // No charge
    });

    it("[CRITICAL] Must handle very large price differences", () => {
      const upgrade = calculateProratedUpgrade(99, 999, 15, "monthly");
      const downgrade = calculateDowngradeCredit(999, 99, 15, "monthly");

      expect(upgrade).toBeGreaterThan(0);
      expect(upgrade).toBeLessThan(999);

      expect(downgrade.creditAmount).toBeGreaterThan(0);
      expect(downgrade.nextBillingCharge).toBeGreaterThanOrEqual(0);
    });
  });

  describe("🚨 CRITICAL: Real Production Scenarios", () => {
    it("[CRITICAL] Qatar clinic upgrade (QAR) must work", () => {
      // Real scenario: Starter (179 GBP) → Professional (209 GBP) in Qatar
      const starterQAR = convertPrice(179, "QAR");
      const professionalQAR = convertPrice(209, "QAR");

      const prorated = calculateProratedUpgrade(
        starterQAR,
        professionalQAR,
        15,
        "monthly",
      );

      expect(prorated).toBeGreaterThan(0);
      expect(prorated).toBeLessThan(professionalQAR);
    });

    it("[CRITICAL] UAE clinic downgrade (AED) must work", () => {
      // Real scenario: Enterprise (349 GBP) → Business (249 GBP) in UAE
      const enterpriseAED = convertPrice(349, "AED");
      const businessAED = convertPrice(249, "AED");

      const credit = calculateDowngradeCredit(
        enterpriseAED,
        businessAED,
        20,
        "monthly",
      );

      expect(credit.creditAmount).toBeGreaterThan(0);
      expect(credit.nextBillingCharge).toBeGreaterThanOrEqual(0);
      expect(credit.nextBillingCharge).toBeLessThan(businessAED);
    });

    it("[CRITICAL] Saudi clinic mid-tier change (SAR) must work", () => {
      // Real scenario: Professional (209 GBP) → Business (249 GBP) in Saudi
      const professionalSAR = convertPrice(209, "SAR");
      const businessSAR = convertPrice(249, "SAR");

      const prorated = calculateProratedUpgrade(
        professionalSAR,
        businessSAR,
        10,
        "monthly",
      );

      expect(prorated).toBeGreaterThan(0);
      expect(prorated).toBeLessThan(businessSAR);
    });
  });

  describe("🚨 CRITICAL: Data Integrity", () => {
    it("[CRITICAL] Calculations must be deterministic (same input = same output)", () => {
      // Run same calculation multiple times
      const results = [];
      for (let i = 0; i < 10; i++) {
        const result = calculateProratedUpgrade(966, 1200, 14, "monthly");
        results.push(result);
      }

      // All results should be identical
      const firstResult = results[0];
      results.forEach((result) => {
        expect(result).toBe(firstResult);
      });
    });

    it("[CRITICAL] Proration must round consistently", () => {
      // Test with difficult rounding scenarios
      const scenarios = [
        { current: 99.99, new: 199.99, days: 15 },
        { current: 333.33, new: 666.66, days: 7 },
        { current: 149.5, new: 249.5, days: 21 },
      ];

      scenarios.forEach(({ current, new: newPrice, days }) => {
        const result = calculateProratedUpgrade(
          current,
          newPrice,
          days,
          "monthly",
        );

        // Should always round to 2 decimal places
        expect(result).toBe(Math.round(result * 100) / 100);

        // Should never have more than 2 decimal places
        const decimals = result.toString().split(".")[1]?.length || 0;
        expect(decimals).toBeLessThanOrEqual(2);
      });
    });
  });

  describe("🚨 CRITICAL: Business Logic Validation", () => {
    it("[CRITICAL] Upgrade must cost more than $0", () => {
      // Upgrading to higher tier must have positive charge
      const result = calculateProratedUpgrade(100, 200, 15, "monthly");
      expect(result).toBeGreaterThan(0);
    });

    it("[CRITICAL] Downgrade must create credit", () => {
      // Downgrading to lower tier must create credit
      const result = calculateDowngradeCredit(200, 100, 15, "monthly");
      expect(result.creditAmount).toBeGreaterThan(0);
    });

    it("[CRITICAL] Credit must reduce next bill", () => {
      const result = calculateDowngradeCredit(1000, 500, 20, "monthly");

      // Next bill should be less than full price
      expect(result.nextBillingCharge).toBeLessThan(500);

      // But not negative
      expect(result.nextBillingCharge).toBeGreaterThanOrEqual(0);
    });

    it("[CRITICAL] Proration must respect billing period", () => {
      const monthly = calculateProratedUpgrade(100, 200, 15, "monthly");
      const yearly = calculateProratedUpgrade(1200, 2400, 180, "yearly");

      // Monthly should use 30-day calculation
      expect(monthly).toBeGreaterThan(0);

      // Yearly should use 365-day calculation
      expect(yearly).toBeGreaterThan(0);

      // Yearly prorated charge should be roughly proportional
      // (but not exactly 12x due to different period lengths)
    });
  });

  describe("🚨 CRITICAL: API Integration Points", () => {
    it("[CRITICAL] Billing service functions must exist", async () => {
      // Verify all required functions are exported
      const billingService = await import("@/lib/services/billing-service");

      expect(billingService.getCurrentUserSubscription).toBeDefined();
      expect(billingService.getAvailablePlans).toBeDefined();
      expect(billingService.calculateProration).toBeDefined();
      expect(billingService.updateSubscriptionPlan).toBeDefined();
      expect(billingService.AVAILABLE_PLANS).toBeDefined();
    });

    it("[CRITICAL] Pricing tiers must be accessible", async () => {
      const config = await import("@/lib/config/pricing-tiers");

      expect(config.PRICING_TIERS).toBeDefined();
      expect(config.PRICING_TIERS.length).toBeGreaterThan(0);
      expect(config.TIER_MAPPING).toBeDefined();
    });

    it("[CRITICAL] All required utilities must be exported", async () => {
      const helpers = await import("@/lib/utils/pricing-helpers");

      expect(helpers.calculateProratedUpgrade).toBeDefined();
      expect(helpers.calculateDowngradeCredit).toBeDefined();
      expect(helpers.shouldChargeSetupFee).toBeDefined();
      expect(helpers.getSetupFeeAmount).toBeDefined();
      expect(helpers.convertPrice).toBeDefined();
      expect(helpers.getDaysUntilBilling).toBeDefined();
      expect(helpers.getCurrencyFromCountry).toBeDefined();
    });
  });

  describe("🚨 CRITICAL: Configuration Validation", () => {
    it("[CRITICAL] All tiers must have Stripe price IDs in production", () => {
      // In production, all tiers must have stripePriceId
      // In test, we just check the structure exists
      PRICING_TIERS.forEach((tier) => {
        expect(tier.id).toBeTruthy();
        // stripePriceId would be set in production env
      });
    });

    it("[CRITICAL] Currency rates must be defined", async () => {
      const { CURRENCY_RATES } = await import("@/lib/utils/pricing-helpers");

      const requiredCurrencies = [
        "GBP",
        "USD",
        "SAR",
        "AED",
        "QAR",
        "KWD",
        "BHD",
        "OMR",
      ];

      requiredCurrencies.forEach((currency) => {
        expect(
          CURRENCY_RATES[currency as keyof typeof CURRENCY_RATES],
        ).toBeDefined();
        expect(
          CURRENCY_RATES[currency as keyof typeof CURRENCY_RATES],
        ).toBeGreaterThan(0);
      });
    });
  });

  describe("🚨 CRITICAL: Component Dependencies", () => {
    it("[CRITICAL] All pricing helper functions are importable", async () => {
      // Verify all required functions can be imported
      const helpers = await import("@/lib/utils/pricing-helpers");

      expect(helpers.calculateProratedUpgrade).toBeDefined();
      expect(helpers.calculateDowngradeCredit).toBeDefined();
      expect(helpers.shouldChargeSetupFee).toBeDefined();
      expect(helpers.getSetupFeeAmount).toBeDefined();
    });

    it("[CRITICAL] Pricing tiers are importable", async () => {
      const config = await import("@/lib/config/pricing-tiers");

      expect(config.PRICING_TIERS).toBeDefined();
      expect(config.PRICING_TIERS.length).toBe(5);
    });
  });

  describe("🎯 Quick Sanity Checks", () => {
    it("All 5 tiers should be defined", () => {
      expect(PRICING_TIERS).toHaveLength(5);
      expect(PRICING_TIERS[0].id).toBe("tier1");
      expect(PRICING_TIERS[4].id).toBe("tier5");
    });

    it("Tier prices should increase", () => {
      for (let i = 1; i < PRICING_TIERS.length; i++) {
        expect(PRICING_TIERS[i].priceGBP).toBeGreaterThanOrEqual(
          PRICING_TIERS[i - 1].priceGBP,
        );
      }
    });

    it("Setup fees should be reasonable (not more than monthly price)", () => {
      PRICING_TIERS.forEach((tier) => {
        expect(tier.setupGBP).toBeLessThanOrEqual(tier.priceGBP * 2);
      });
    });

    it("All tiers should have bilingual names", () => {
      PRICING_TIERS.forEach((tier) => {
        expect(tier.nameEn).toBeTruthy();
        expect(tier.nameAr).toBeTruthy();
        expect(tier.nameEn).not.toBe(tier.nameAr); // Different languages
      });
    });

    it("All tiers should have features", () => {
      PRICING_TIERS.forEach((tier) => {
        expect(tier.featuresEn.length).toBeGreaterThan(0);
        expect(tier.featuresAr.length).toBeGreaterThan(0);
        expect(tier.featuresEn.length).toBe(tier.featuresAr.length);
      });
    });
  });

  describe("🔥 Performance Benchmarks", () => {
    it("[BENCHMARK] Proration calculation should be fast (<1ms)", () => {
      const iterations = 1000;
      const startTime = performance.now();

      for (let i = 0; i < iterations; i++) {
        calculateProratedUpgrade(966, 1200, 14, "monthly");
      }

      const endTime = performance.now();
      const avgTime = (endTime - startTime) / iterations;

      expect(avgTime).toBeLessThan(1); // Less than 1ms per calculation
    });

    it("[BENCHMARK] Currency conversion should be instant", () => {
      const iterations = 10000;
      const startTime = performance.now();

      for (let i = 0; i < iterations; i++) {
        convertPrice(100, "SAR");
      }

      const endTime = performance.now();
      const avgTime = (endTime - startTime) / iterations;

      expect(avgTime).toBeLessThan(0.1); // Less than 0.1ms per conversion
    });
  });
});

describe("Pre-Deployment Checklist", () => {
  test("✅ All pricing calculations work correctly", () => {
    expect(calculateProratedUpgrade(966, 1200, 14, "monthly")).toBeCloseTo(
      109.2,
      0,
    );
    expect(
      calculateDowngradeCredit(966, 500, 14, "monthly").creditAmount,
    ).toBeCloseTo(217.47, 0);
  });

  test("✅ Setup fee protection is active", () => {
    const tier: PricingTier = {
      id: "tier2",
      nameEn: "Pro",
      nameAr: "محترف",
      priceGBP: 299,
      setupGBP: 199,
      popular: true,
      featuresEn: [],
      featuresAr: [],
    };

    expect(shouldChargeSetupFee(true, tier)).toBe(false);
  });

  test("✅ All currencies supported", () => {
    ["GBP", "USD", "EUR", "SAR", "AED", "QAR", "KWD", "BHD", "OMR"].forEach(
      (currency) => {
        const result = convertPrice(100, currency as any);
        expect(result).toBeGreaterThan(0);
      },
    );
  });

  test("✅ All 5 tiers configured correctly", () => {
    expect(PRICING_TIERS).toHaveLength(5);
    PRICING_TIERS.forEach((tier) => {
      expect(tier.id).toBeTruthy();
      expect(tier.nameEn).toBeTruthy();
      expect(tier.nameAr).toBeTruthy();
      expect(tier.priceGBP).toBeGreaterThan(0);
    });
  });

  test("✅ No negative charges possible", () => {
    const testCases = [
      { current: 1000, new: 500, days: 29 },
      { current: 500, new: 1000, days: 1 },
      { current: 200, new: 100, days: 15 },
    ];

    testCases.forEach(({ current, new: newPrice, days }) => {
      const upgrade = calculateProratedUpgrade(
        current,
        newPrice,
        days,
        "monthly",
      );
      const downgrade = calculateDowngradeCredit(
        current,
        newPrice,
        days,
        "monthly",
      );

      expect(upgrade).toBeGreaterThanOrEqual(0);
      expect(downgrade.nextBillingCharge).toBeGreaterThanOrEqual(0);
    });
  });
});

/**
 * DEPLOYMENT VALIDATION
 * Run this test suite before every production deployment!
 *
 * Command: npm run test:unit -- billing-critical-paths.test.ts
 *
 * All tests must pass before deploying billing changes.
 */
