// Payment Service Edge Cases Unit Tests

import { paymentService } from '@/core/payments/payment.service';
import { createTestSovereignBank, createTestBankAccount, cleanDatabase } from '@/__tests__/utils/test-db';
import { testPrisma } from '@/__tests__/utils/test-db';
import { PaymentPriority } from '@/shared/types';

describe('PaymentService - Edge Cases', () => {
  beforeEach(async () => {
    await cleanDatabase();
  });

  afterAll(async () => {
    await testPrisma.$disconnect();
  });

  describe('Currency Mismatch Handling', () => {
    it('should reject payment when currencies do not match', async () => {
      const bank = await createTestSovereignBank();
      const sourceAccount = await createTestBankAccount({
        sovereignBankId: bank.id,
        currencyCode: 'USD',
        balance: '1000.00',
      });
      const destAccount = await createTestBankAccount({
        sovereignBankId: bank.id,
        currencyCode: 'EUR',
        balance: '500.00',
      });

      await expect(
        paymentService.initiatePayment({
          debtorAccount: sourceAccount.accountNumber,
          creditorAccount: destAccount.accountNumber,
          amount: '100.00',
          currency: 'USD',
          priority: PaymentPriority.NORMAL,
          assetType: 'fiat',
        })
      ).rejects.toThrow();
    });
  });

  describe('Large Amount Handling', () => {
    it('should handle very large payment amounts', async () => {
      const bank = await createTestSovereignBank();
      const sourceAccount = await createTestBankAccount({
        sovereignBankId: bank.id,
        balance: '999999999.99',
      });
      const destAccount = await createTestBankAccount({
        sovereignBankId: bank.id,
      });

      const result = await paymentService.initiatePayment({
        debtorAccount: sourceAccount.accountNumber,
        creditorAccount: destAccount.accountNumber,
        amount: '999999999.99',
        currency: 'USD',
        priority: PaymentPriority.RTGS,
        assetType: 'fiat',
      });

      expect(result.status).toBe('settled');
    });

    it('should reject payment exceeding account balance', async () => {
      const bank = await createTestSovereignBank();
      const sourceAccount = await createTestBankAccount({
        sovereignBankId: bank.id,
        balance: '1000.00',
      });
      const destAccount = await createTestBankAccount({
        sovereignBankId: bank.id,
      });

      await expect(
        paymentService.initiatePayment({
          debtorAccount: sourceAccount.accountNumber,
          creditorAccount: destAccount.accountNumber,
          amount: '1001.00',
          currency: 'USD',
          priority: PaymentPriority.NORMAL,
          assetType: 'fiat',
        })
      ).rejects.toThrow('Insufficient');
    });
  });

  describe('Concurrent Payments', () => {
    it('should handle multiple concurrent payments from same account', async () => {
      const bank = await createTestSovereignBank();
      const sourceAccount = await createTestBankAccount({
        sovereignBankId: bank.id,
        balance: '1000.00',
      });
      const destAccount1 = await createTestBankAccount({
        sovereignBankId: bank.id,
      });
      const destAccount2 = await createTestBankAccount({
        sovereignBankId: bank.id,
      });

      // Simulate concurrent payments
      const payment1 = paymentService.initiatePayment({
        debtorAccount: sourceAccount.accountNumber,
        creditorAccount: destAccount1.accountNumber,
        amount: '300.00',
        currency: 'USD',
        priority: PaymentPriority.NORMAL,
        assetType: 'fiat',
      });

      const payment2 = paymentService.initiatePayment({
        debtorAccount: sourceAccount.accountNumber,
        creditorAccount: destAccount2.accountNumber,
        amount: '300.00',
        currency: 'USD',
        priority: PaymentPriority.NORMAL,
        assetType: 'fiat',
      });

      const results = await Promise.allSettled([payment1, payment2]);

      // At least one should succeed, but both might fail if balance is insufficient
      const succeeded = results.filter((r) => r.status === 'fulfilled').length;
      expect(succeeded).toBeGreaterThanOrEqual(0);
    });
  });

  describe('Zero and Negative Amounts', () => {
    it('should reject zero amount payments', async () => {
      const bank = await createTestSovereignBank();
      const sourceAccount = await createTestBankAccount({
        sovereignBankId: bank.id,
        balance: '1000.00',
      });
      const destAccount = await createTestBankAccount({
        sovereignBankId: bank.id,
      });

      await expect(
        paymentService.initiatePayment({
          debtorAccount: sourceAccount.accountNumber,
          creditorAccount: destAccount.accountNumber,
          amount: '0.00',
          currency: 'USD',
          priority: PaymentPriority.NORMAL,
          assetType: 'fiat',
        })
      ).rejects.toThrow();
    });

    it('should reject negative amount payments', async () => {
      const bank = await createTestSovereignBank();
      const sourceAccount = await createTestBankAccount({
        sovereignBankId: bank.id,
        balance: '1000.00',
      });
      const destAccount = await createTestBankAccount({
        sovereignBankId: bank.id,
      });

      await expect(
        paymentService.initiatePayment({
          debtorAccount: sourceAccount.accountNumber,
          creditorAccount: destAccount.accountNumber,
          amount: '-100.00',
          currency: 'USD',
          priority: PaymentPriority.NORMAL,
          assetType: 'fiat',
        })
      ).rejects.toThrow();
    });
  });
});

