import { MembershipFeeViewModel } from '@/lib/view-models/MembershipFeeViewModel'; import { PaymentViewModel } from '@/lib/view-models/PaymentViewModel'; import { PrizeViewModel } from '@/lib/view-models/PrizeViewModel'; import { WalletViewModel } from '@/lib/view-models/WalletViewModel'; import type { PaymentsApiClient } from '../../api/payments/PaymentsApiClient'; import type { PaymentDTO } from '../../types/generated/PaymentDTO'; import type { PrizeDTO } from '../../types/generated/PrizeDTO'; // Local payment creation request matching the Payments API contract until a shared generated type is introduced type CreatePaymentRequest = { type: 'sponsorship' | 'membership_fee'; amount: number; payerId: string; payerType: 'sponsor' | 'driver'; leagueId: string; seasonId?: string; }; /** * Payment Service * * Orchestrates payment operations by coordinating API calls and view model creation. * All dependencies are injected via constructor. */ export class PaymentService { constructor( private readonly apiClient: PaymentsApiClient ) {} /** * Get all payments with optional filters */ async getPayments(leagueId?: string, payerId?: string): Promise { const query = (leagueId || payerId) ? { ...(leagueId && { leagueId }), ...(payerId && { payerId }) } : undefined; const dto = await this.apiClient.getPayments(query); return (dto?.payments || []).map((payment: PaymentDTO) => new PaymentViewModel(payment)); } /** * Get single payment by ID */ async getPayment(paymentId: string): Promise { // Note: Assuming the API returns a single payment from the list const dto = await this.apiClient.getPayments(); const payment = (dto?.payments || []).find((p: PaymentDTO) => p.id === paymentId); if (!payment) { throw new Error(`Payment with ID ${paymentId} not found`); } return new PaymentViewModel(payment); } /** * Create a new payment */ async createPayment(input: CreatePaymentRequest): Promise { const dto = await this.apiClient.createPayment(input); return new PaymentViewModel(dto.payment); } /** * Get membership fees for a league */ async getMembershipFees(leagueId: string, driverId?: string): Promise { const dto = await this.apiClient.getMembershipFees({ leagueId, ...(driverId && { driverId }) }); return dto.fee ? new MembershipFeeViewModel(dto.fee) : null; } /** * Get prizes with optional filters */ async getPrizes(leagueId?: string, seasonId?: string): Promise { const query = (leagueId || seasonId) ? { ...(leagueId && { leagueId }), ...(seasonId && { seasonId }) } : undefined; const dto = await this.apiClient.getPrizes(query); return (dto?.prizes || []).map((prize: PrizeDTO) => new PrizeViewModel(prize)); } /** * Get wallet for a league */ async getWallet(leagueId: string): Promise { const dto = await this.apiClient.getWallet({ leagueId }); return new WalletViewModel({ ...dto.wallet, transactions: dto.transactions }); } /** * Get payment history for a user (driver) */ async getPaymentHistory(payerId: string): Promise { return await this.getPayments(undefined, payerId); } }