import { ref, computed, onUnmounted } from 'vue' import { purchaseTicket, checkPaymentStatus, payInvoiceWithWallet } from '@/lib/api/events' import { useAuth } from './useAuth' import { toast } from 'vue-sonner' export function useTicketPurchase() { const { isAuthenticated, currentUser } = useAuth() // State const isLoading = ref(false) const error = ref(null) const paymentHash = ref(null) const paymentRequest = ref(null) const qrCode = ref(null) const isPaymentPending = ref(false) const isPayingWithWallet = ref(false) // Ticket QR code state const ticketQRCode = ref(null) const purchasedTicketId = ref(null) const showTicketQR = 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) } }) const userWallets = computed(() => { const wallets = currentUser.value?.wallets || [] console.log('User wallets computed:', { currentUser: currentUser.value, wallets: wallets, walletCount: wallets.length, hasWallets: wallets.length > 0 }) return wallets }) const hasWalletWithBalance = computed(() => { const hasBalance = userWallets.value.some((wallet: any) => wallet.balance_msat > 0) console.log('Wallet balance check:', { wallets: userWallets.value, hasBalance: hasBalance, walletBalances: userWallets.value.map((w: any) => ({ id: w.id, balance: w.balance_msat })) }) return hasBalance }) // Generate QR code for Lightning payment async function generateQRCode(bolt11: string) { try { const qrcode = await import('qrcode') const dataUrl = await qrcode.toDataURL(bolt11, { width: 256, margin: 2, color: { dark: '#000000', light: '#FFFFFF' } }) qrCode.value = dataUrl } catch (err) { console.error('Error generating QR code:', err) error.value = 'Failed to generate QR code' } } // Generate QR code for ticket async function generateTicketQRCode(ticketId: string) { try { const qrcode = await import('qrcode') const ticketUrl = `ticket://${ticketId}` const dataUrl = await qrcode.toDataURL(ticketUrl, { width: 128, margin: 2, color: { dark: '#000000', light: '#FFFFFF' } }) ticketQRCode.value = dataUrl return dataUrl } catch (error) { console.error('Error generating ticket QR code:', error) return null } } // Pay with wallet async function payWithWallet(paymentRequest: string) { const walletWithBalance = userWallets.value.find((wallet: any) => wallet.balance_msat > 0) if (!walletWithBalance) { throw new Error('No wallet with sufficient balance found') } try { await payInvoiceWithWallet(paymentRequest, walletWithBalance.id, walletWithBalance.adminkey) 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') } isLoading.value = true error.value = null paymentHash.value = null paymentRequest.value = null qrCode.value = null ticketQRCode.value = null purchasedTicketId.value = null showTicketQR.value = false try { // 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) { isPayingWithWallet.value = true 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) isPayingWithWallet.value = false await startPaymentStatusCheck(eventId, invoice.payment_hash) } } else { // No wallet balance, proceed with manual payment await startPaymentStatusCheck(eventId, invoice.payment_hash) } } catch (err) { error.value = err instanceof Error ? err.message : 'Failed to purchase ticket' console.error('Error purchasing ticket:', err) } finally { isLoading.value = false } } // Start payment status check async function startPaymentStatusCheck(eventId: string, hash: string) { isPaymentPending.value = true let checkInterval: NodeJS.Timeout | 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) } // Stop payment status check function stopPaymentStatusCheck() { isPaymentPending.value = false } // Reset payment state function resetPaymentState() { isLoading.value = false error.value = null paymentHash.value = null paymentRequest.value = null qrCode.value = null isPaymentPending.value = false isPayingWithWallet.value = false ticketQRCode.value = null purchasedTicketId.value = null showTicketQR.value = false } // Open Lightning wallet function handleOpenLightningWallet() { if (paymentRequest.value) { window.open(`lightning:${paymentRequest.value}`, '_blank') } } // Cleanup function function cleanup() { stopPaymentStatusCheck() } // Lifecycle onUnmounted(() => { cleanup() }) return { // State isLoading, error, paymentHash, paymentRequest, qrCode, isPaymentPending, isPayingWithWallet, ticketQRCode, purchasedTicketId, showTicketQR, // Computed canPurchase, userDisplay, userWallets, hasWalletWithBalance, // Actions purchaseTicketForEvent, handleOpenLightningWallet, resetPaymentState, cleanup, generateTicketQRCode } }