import { ref, computed } from 'vue' import { purchaseTicket, checkPaymentStatus, payInvoiceWithWallet } from '@/lib/api/events' import { useAuth } from './useAuth' import { toast } from 'vue-sonner' interface Wallet { id: string user: string name: string adminkey: string inkey: string deleted: boolean created_at: string updated_at: string currency?: string balance_msat: number extra?: { icon: string color: string pinned: boolean } } export function useTicketPurchase() { const { isAuthenticated, currentUser } = useAuth() const isLoading = ref(false) const error = ref(null) const paymentHash = ref('') const paymentRequest = ref('') const qrCode = ref('') const isPaymentPending = ref(false) const paymentCheckInterval = ref(null) const isPayingWithWallet = ref(false) const canPurchase = computed(() => { return isAuthenticated.value && !isLoading.value }) const userDisplay = computed(() => { if (!currentUser.value) return null return { name: currentUser.value.username || currentUser.value.email || 'Anonymous', id: currentUser.value.id, shortId: currentUser.value.id.slice(0, 8) + '...' + currentUser.value.id.slice(-8) } }) const userWallets = computed(() => { if (!currentUser.value) return [] as Wallet[] return currentUser.value.wallets || [] }) const hasWalletWithBalance = computed(() => { return userWallets.value.some((wallet: Wallet) => wallet.balance_msat > 0) }) async function generateQRCode(bolt11: string) { try { const QRCode = await import('qrcode') qrCode.value = await QRCode.toDataURL(`lightning:${bolt11}`) } catch (err) { console.error('Failed to generate QR code:', err) } } async function payWithWallet(paymentRequest: string) { if (!currentUser.value || !userWallets.value.length) { throw new Error('No wallet available for payment') } // Find the first wallet with sufficient balance const wallet = userWallets.value.find((w: Wallet) => w.balance_msat > 0) if (!wallet) { throw new Error('No wallet with sufficient balance found') } try { isPayingWithWallet.value = true const result = await payInvoiceWithWallet(paymentRequest, wallet.id, wallet.adminkey) toast.success(`Payment successful! Fee: ${result.fee_msat} msat`) return result } catch (err) { const message = err instanceof Error ? err.message : 'Failed to pay with wallet' toast.error(message) throw err } finally { isPayingWithWallet.value = false } } async function purchaseTicketForEvent(eventId: string) { if (!isAuthenticated.value) { error.value = 'Please log in to purchase tickets' toast.error('Please log in to purchase tickets') return } try { isLoading.value = true error.value = '' // Step 1: Get the invoice const result = await purchaseTicket(eventId) paymentHash.value = result.payment_hash paymentRequest.value = result.payment_request await generateQRCode(result.payment_request) // Step 2: Try to pay with wallet if user has balance if (hasWalletWithBalance.value) { try { await payWithWallet(result.payment_request) // Payment successful, start monitoring for ticket confirmation startPaymentStatusCheck(eventId, result.payment_hash) return } catch (walletPaymentError) { console.log('Wallet payment failed, showing QR code for manual payment:', walletPaymentError) // Fall back to QR code payment startPaymentStatusCheck(eventId, result.payment_hash) } } else { // No wallet balance, show QR code for manual payment startPaymentStatusCheck(eventId, result.payment_hash) } toast.success('Payment request generated successfully') } catch (err) { const message = err instanceof Error ? err.message : 'Failed to generate payment request' error.value = message toast.error(message) throw err } finally { isLoading.value = false } } function startPaymentStatusCheck(eventId: string, paymentHash: string) { isPaymentPending.value = true // Clear any existing interval if (paymentCheckInterval.value) { clearInterval(paymentCheckInterval.value) } // Check payment status every 2 seconds paymentCheckInterval.value = window.setInterval(async () => { try { const status = await checkPaymentStatus(eventId, paymentHash) if (status.paid) { // Payment successful clearInterval(paymentCheckInterval.value!) paymentCheckInterval.value = null isPaymentPending.value = false toast.success('Payment successful! Your ticket has been purchased.') // Reset payment state resetPaymentState() return { success: true, ticketId: status.ticket_id } } } catch (err) { console.error('Error checking payment status:', err) // Don't show error to user for status checks, just log it } }, 2000) } function stopPaymentStatusCheck() { if (paymentCheckInterval.value) { clearInterval(paymentCheckInterval.value) paymentCheckInterval.value = null } isPaymentPending.value = false } function resetPaymentState() { paymentHash.value = '' paymentRequest.value = '' qrCode.value = '' error.value = '' stopPaymentStatusCheck() } function handleOpenLightningWallet() { if (paymentRequest.value) { window.location.href = `lightning:${paymentRequest.value}` } } // Cleanup on unmount function cleanup() { stopPaymentStatusCheck() } return { // State isLoading, error, paymentHash, paymentRequest, qrCode, isPaymentPending, isPayingWithWallet, canPurchase, userDisplay, userWallets, hasWalletWithBalance, // Actions purchaseTicketForEvent, payWithWallet, handleOpenLightningWallet, resetPaymentState, cleanup, } }