// Payment Services - Domestic and Cross-Border Payments

import { PaymentRequest, PaymentStatus, PaymentPriority, AssetType } from '@/shared/types';
import { ledgerService } from '@/core/ledger/ledger.service';
import { ledgerLifecycleService } from '@/core/ledger/ledger-lifecycle.service';
import { accountService } from '@/core/accounts/account.service';
import { LedgerEntryType } from '@/shared/types';
import { v4 as uuidv4 } from 'uuid';
import { DbisError, ErrorCode } from '@/shared/types';

export class PaymentService {
  /**
   * Initiate a payment
   */
  async initiatePayment(request: PaymentRequest): Promise<PaymentStatus> {
    const paymentId = `PAY-${uuidv4()}`;

    // Validate accounts
    const debtorAccount = await accountService.getAccountByNumber(request.debtorAccount);
    const creditorAccount = await accountService.getAccountByNumber(request.creditorAccount);

    if (!debtorAccount || !creditorAccount) {
      throw new DbisError(ErrorCode.NOT_FOUND, 'Account not found');
    }

    // Validate balance
    const amount = parseFloat(request.amount);
    const availableBalance = parseFloat(debtorAccount.availableBalance);
    if (availableBalance < amount) {
      throw new DbisError(ErrorCode.VALIDATION_ERROR, 'Insufficient balance');
    }

    // Determine settlement mode based on priority
    const settlementMode = this.getSettlementMode(request.priority);

    // Create multi-entry transaction
    const transaction = {
      referenceId: paymentId,
      entries: [
        {
          debitAccountId: debtorAccount.id,
          creditAccountId: creditorAccount.id,
          amount: request.amount,
          currencyCode: request.currency,
          assetType: request.assetType,
        },
      ],
    };

    // Process through ledger lifecycle
    const ledgerId = debtorAccount.sovereignBankId;
    const postingResult = await ledgerLifecycleService.processTransaction(
      ledgerId,
      transaction,
      LedgerEntryType.TYPE_A, // Fiat transfer
      undefined,
      {
        paymentId,
        priority: request.priority,
        reference: request.reference,
        settlementMode,
      }
    );

    return {
      paymentId,
      status: 'settled',
      ledgerEntryIds: postingResult.entryIds,
    };
  }

  /**
   * Get payment status
   */
  async getPaymentStatus(paymentId: string): Promise<PaymentStatus> {
    const entries = await ledgerService.getEntriesByReference(paymentId);

    if (entries.length === 0) {
      throw new DbisError(ErrorCode.NOT_FOUND, 'Payment not found');
    }

    const status = entries[0].status === 'settled' ? 'settled' : 'processing';

    return {
      paymentId,
      status,
      ledgerEntryIds: entries.map((e) => e.id),
    };
  }

  /**
   * Get settlement mode based on priority
   */
  private getSettlementMode(priority: PaymentPriority): string {
    switch (priority) {
      case PaymentPriority.RTGS:
        return 'RTGS';
      case PaymentPriority.URGENT:
        return 'RTGS';
      case PaymentPriority.DNS:
        return 'DNS';
      case PaymentPriority.NORMAL:
        return 'DNS';
      default:
        return 'DNS';
    }
  }
}

export const paymentService = new PaymentService();

