import { Result } from '../../../shared/result/Result'; import type { ILogger } from '../../../shared/src/logging/ILogger'; import type { CheckoutServicePort } from '../ports/CheckoutServicePort'; import type { CheckoutConfirmationPort } from '../ports/CheckoutConfirmationPort'; import { CheckoutStateEnum } from '../../domain/value-objects/CheckoutState'; interface SessionMetadata { sessionName: string; trackId: string; carIds: string[]; } export class ConfirmCheckoutUseCase { private static readonly DEFAULT_TIMEOUT_MS = 30000; constructor( private readonly checkoutService: CheckoutServicePort, private readonly confirmationPort: CheckoutConfirmationPort, private readonly logger: ILogger, ) {} async execute(sessionMetadata?: SessionMetadata): Promise> { this.logger.debug('Executing ConfirmCheckoutUseCase', { sessionMetadata }); const infoResult = await this.checkoutService.extractCheckoutInfo(); if (infoResult.isErr()) { this.logger.error('Failed to extract checkout info', { error: infoResult.unwrapErr() }); return Result.err(infoResult.unwrapErr()); } const info = infoResult.unwrap(); this.logger.info('Extracted checkout info', { state: info.state.getValue(), price: info.price }); if (info.state.getValue() === CheckoutStateEnum.INSUFFICIENT_FUNDS) { this.logger.error('Insufficient funds to complete checkout'); return Result.err(new Error('Insufficient funds to complete checkout')); } if (!info.price) { this.logger.error('Could not extract price from checkout page'); return Result.err(new Error('Could not extract price from checkout page')); } this.logger.debug('Requesting checkout confirmation', { price: info.price, state: info.state.getValue(), sessionMetadata }); // Request confirmation via port with full checkout context const confirmationResult = await this.confirmationPort.requestCheckoutConfirmation({ price: info.price, state: info.state, sessionMetadata: sessionMetadata || { sessionName: 'Unknown Session', trackId: 'unknown', carIds: [], }, timeoutMs: ConfirmCheckoutUseCase.DEFAULT_TIMEOUT_MS, }); if (confirmationResult.isErr()) { this.logger.error('Checkout confirmation failed', { error: confirmationResult.unwrapErr() }); return Result.err(confirmationResult.unwrapErr()); } const confirmation = confirmationResult.unwrap(); this.logger.info('Checkout confirmation received', { confirmation }); if (confirmation.isCancelled()) { this.logger.error('Checkout cancelled by user'); return Result.err(new Error('Checkout cancelled by user')); } if (confirmation.isTimeout()) { this.logger.error('Checkout confirmation timeout'); return Result.err(new Error('Checkout confirmation timeout')); } this.logger.info('Proceeding with checkout'); const checkoutResult = await this.checkoutService.proceedWithCheckout(); if (checkoutResult.isOk()) { this.logger.info('Checkout process completed successfully.'); } else { this.logger.error('Checkout process failed', { error: checkoutResult.unwrapErr() }); } return checkoutResult; } }