import 'package:pshared/models/payment/operation.dart'; import 'package:pshared/models/payment/payment.dart'; import 'package:pshared/models/payment/status.dart'; OperationItem mapPaymentToOperation(Payment payment) { final debit = payment.lastQuote?.debitAmount; final settlement = payment.lastQuote?.expectedSettlementAmount; final amountMoney = debit ?? settlement; final amount = _parseAmount(amountMoney?.amount); final currency = amountMoney?.currency ?? ''; final toAmount = settlement == null ? amount : _parseAmount(settlement.amount); final toCurrency = settlement?.currency ?? currency; final payId = _firstNonEmpty([ payment.paymentRef, payment.idempotencyKey, ]) ?? '-'; final name = _firstNonEmpty([ payment.lastQuote?.quoteRef, payment.paymentRef, payment.idempotencyKey, ]) ?? '-'; final comment = _firstNonEmpty([ payment.failureReason, payment.failureCode, payment.state, ]) ?? ''; return OperationItem( status: statusFromPayment(payment), fileName: _extractFileName(payment.metadata), amount: amount, currency: currency, toAmount: toAmount, toCurrency: toCurrency, payId: payId, paymentRef: payment.paymentRef, cardNumber: null, name: name, date: resolvePaymentDate(payment), comment: comment, ); } OperationStatus statusFromPayment(Payment payment) { final normalized = _normalizePaymentState(payment.state); switch (normalized) { case 'SUCCESS': return OperationStatus.success; case 'FAILED': case 'CANCELLED': return OperationStatus.error; default: return OperationStatus.processing; } } DateTime resolvePaymentDate(Payment payment) { final createdAt = payment.createdAt; if (createdAt != null) return createdAt.toLocal(); final expiresAt = payment.lastQuote?.fxQuote?.expiresAtUnixMs; if (expiresAt != null && expiresAt > 0) { return DateTime.fromMillisecondsSinceEpoch(expiresAt, isUtc: true).toLocal(); } return DateTime.fromMillisecondsSinceEpoch(0); } String? paymentIdFromOperation(OperationItem operation) { final candidates = [ operation.paymentRef, operation.payId, ]; for (final candidate in candidates) { final trimmed = candidate?.trim(); if (trimmed != null && trimmed.isNotEmpty && trimmed != '-') { return trimmed; } } return null; } String? _extractFileName(Map? metadata) { if (metadata == null || metadata.isEmpty) return null; return _firstNonEmpty([ metadata['upload_filename'], metadata['upload_file_name'], metadata['filename'], ]); } String? _firstNonEmpty(List values) { for (final value in values) { final trimmed = value?.trim(); if (trimmed != null && trimmed.isNotEmpty) return trimmed; } return null; } String _normalizePaymentState(String? raw) { final trimmed = (raw ?? '').trim().toUpperCase(); if (trimmed.startsWith('PAYMENT_STATE_')) { return trimmed.substring('PAYMENT_STATE_'.length); } return trimmed; } double _parseAmount(String? amount) { if (amount == null || amount.trim().isEmpty) return 0; return double.tryParse(amount) ?? 0; }