import { ref, computed, onUnmounted, onMounted } from 'vue' import { purchaseTicket, checkPaymentStatus } from '@/lib/api/events' import { useAuth } from '@/composables/useAuth' import { toast } from 'vue-sonner' import { useAsyncOperation } from '@/core/composables/useAsyncOperation' import { injectService, SERVICE_TOKENS } from '@/core/di-container' import type { PaymentService } from '@/core/services/PaymentService' export function useTicketPurchase() { const { isAuthenticated, currentUser } = useAuth() const paymentService = injectService(SERVICE_TOKENS.PAYMENT_SERVICE) as PaymentService // Async operations const purchaseOperation = useAsyncOperation() // State const paymentHash = ref(null) const paymentRequest = ref(null) const qrCode = ref(null) const isPaymentPending = ref(false) // Ticket QR code state const ticketQRCode = ref(null) const purchasedTicketId = ref(null) const showTicketQR = ref(false) // Wallet state (loaded asynchronously) const userWallets = ref([]) const hasWalletWithBalance = ref(false) // Computed properties const canPurchase = computed(() => isAuthenticated.value && currentUser.value) const userDisplay = computed(() => { if (!currentUser.value) return null return { name: currentUser.value.username || currentUser.value.id, shortId: currentUser.value.id.slice(0, 8) } }) // Delegate to PaymentService for processing status const isPayingWithWallet = computed(() => paymentService.isProcessingPayment.value) // computed ref // Load wallets asynchronously async function loadWallets() { try { const wallets = await paymentService.getUserWalletsAsync() userWallets.value = wallets hasWalletWithBalance.value = await paymentService.hasWalletWithBalanceAsync() console.log('Loaded wallets for ticket purchase:', { count: wallets.length, hasBalance: hasWalletWithBalance.value }) } catch (error) { console.error('Failed to load wallets:', error) userWallets.value = [] hasWalletWithBalance.value = false } } // Load wallets on mount onMounted(() => { loadWallets() }) // Generate QR code for Lightning payment - delegate to PaymentService async function generateQRCode(bolt11: string) { try { qrCode.value = await paymentService.generateQRCode(bolt11) } catch (err) { console.error('Error generating QR code:', err) // Note: error handling is now managed by the purchaseOperation } } // Generate QR code for ticket - delegate to PaymentService async function generateTicketQRCode(ticketId: string) { try { const ticketUrl = `ticket://${ticketId}` const dataUrl = await paymentService.generateCustomQRCode(ticketUrl, { width: 128, margin: 2 }) ticketQRCode.value = dataUrl return dataUrl } catch (error) { console.error('Error generating ticket QR code:', error) return null } } // Pay with wallet - delegate to PaymentService async function payWithWallet(paymentRequest: string) { try { await paymentService.payWithWallet(paymentRequest, undefined, { showToast: false // We'll handle success notifications in the ticket purchase flow }) return true } catch (error) { console.error('Wallet payment failed:', error) throw error } } // Purchase ticket for event async function purchaseTicketForEvent(eventId: string) { if (!canPurchase.value) { throw new Error('User must be authenticated to purchase tickets') } return await purchaseOperation.execute(async () => { // Clear previous state paymentHash.value = null paymentRequest.value = null qrCode.value = null ticketQRCode.value = null purchasedTicketId.value = null showTicketQR.value = false // Get the invoice const invoice = await purchaseTicket(eventId) paymentHash.value = invoice.payment_hash paymentRequest.value = invoice.payment_request // Generate QR code for payment await generateQRCode(invoice.payment_request) // Try to pay with wallet if available if (hasWalletWithBalance.value) { try { await payWithWallet(invoice.payment_request) // If wallet payment succeeds, proceed to check payment status await startPaymentStatusCheck(eventId, invoice.payment_hash) } catch (walletError) { // If wallet payment fails, fall back to manual payment console.log('Wallet payment failed, falling back to manual payment:', walletError) await startPaymentStatusCheck(eventId, invoice.payment_hash) } } else { // No wallet balance, proceed with manual payment await startPaymentStatusCheck(eventId, invoice.payment_hash) } return invoice }, { errorMessage: 'Failed to purchase ticket' }) } // Start payment status check async function startPaymentStatusCheck(eventId: string, hash: string) { isPaymentPending.value = true let checkInterval: number | null = null const checkPayment = async () => { try { const result = await checkPaymentStatus(eventId, hash) if (result.paid) { isPaymentPending.value = false if (checkInterval) { clearInterval(checkInterval) } // Generate ticket QR code if (result.ticket_id) { purchasedTicketId.value = result.ticket_id await generateTicketQRCode(result.ticket_id) showTicketQR.value = true } toast.success('Ticket purchased successfully!') } } catch (err) { console.error('Error checking payment status:', err) } } // Check immediately await checkPayment() // Then check every 2 seconds checkInterval = setInterval(checkPayment, 2000) as unknown as number } // Stop payment status check function stopPaymentStatusCheck() { isPaymentPending.value = false } // Reset payment state function resetPaymentState() { purchaseOperation.clear() paymentHash.value = null paymentRequest.value = null qrCode.value = null isPaymentPending.value = false ticketQRCode.value = null purchasedTicketId.value = null showTicketQR.value = false } // Open Lightning wallet - delegate to PaymentService function handleOpenLightningWallet() { if (paymentRequest.value) { paymentService.openExternalWallet(paymentRequest.value) } } // Cleanup function function cleanup() { stopPaymentStatusCheck() } // Lifecycle onUnmounted(() => { cleanup() }) return { // State isLoading: purchaseOperation.isLoading, error: purchaseOperation.error, paymentHash, paymentRequest, qrCode, isPaymentPending, isPayingWithWallet, ticketQRCode, purchasedTicketId, showTicketQR, // Computed canPurchase, userDisplay, userWallets, hasWalletWithBalance, // Actions purchaseTicketForEvent, handleOpenLightningWallet, resetPaymentState, cleanup, generateTicketQRCode, loadWallets } }