import { decodeEventLog, formatUnits } from 'viem';
import { logPaymentStatusCheckCompleted, logPaymentStatusCheckError, logPaymentStatusCheckStarted, } from '../../core/telemetry/events/payment.js';
import { ERC20_TRANSFER_ABI, TOKENS } from './constants.js';
/**
 * Check the status of a payment transaction using its transaction ID (userOp hash)
 *
 * @param options - Payment status check options
 * @returns Promise<PaymentStatus> - Status information about the payment
 * @throws Error if unable to connect to the RPC endpoint or if the RPC request fails
 *
 * @example
 * ```typescript
 * try {
 *   const status = await getPaymentStatus({
 *     id: "0x1234...5678",
 *     testnet: true
 *   })
 *
 *   if (status.status === 'failed') {
 *     console.log(`Payment failed: ${status.reason}`)
 *   }
 * } catch (error) {
 *   console.error('Unable to check payment status:', error.message)
 * }
 * ```
 *
 * @note The id is the userOp hash returned from the pay function
 */
export async function getPaymentStatus(options) {
    var _a;
    const { id, testnet = false, telemetry = true } = options;
    // Generate correlation ID for this status check
    const correlationId = crypto.randomUUID();
    // Log status check started
    if (telemetry) {
        logPaymentStatusCheckStarted({ testnet, correlationId });
    }
    try {
        // Get the bundler URL based on network
        const bundlerUrl = testnet
            ? 'https://api.developer.coinbase.com/rpc/v1/base-sepolia/S-fOd2n2Oi4fl4e1Crm83XeDXZ7tkg8O'
            : 'https://api.developer.coinbase.com/rpc/v1/base/S-fOd2n2Oi4fl4e1Crm83XeDXZ7tkg8O';
        // Call eth_getUserOperationReceipt via the bundler
        const receipt = await fetch(bundlerUrl, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                jsonrpc: '2.0',
                id: 1,
                method: 'eth_getUserOperationReceipt',
                params: [id],
            }),
        }).then((res) => res.json());
        // Handle RPC errors
        if (receipt.error) {
            console.error('[getPaymentStatus] RPC error:', receipt.error);
            const errorMessage = receipt.error.message || 'Network error';
            if (telemetry) {
                logPaymentStatusCheckError({ testnet, correlationId, errorMessage });
            }
            // Re-throw error for RPC failures
            throw new Error(`RPC error: ${errorMessage}`);
        }
        // If no result, payment is still pending or not found
        if (!receipt.result) {
            // Try eth_getUserOperationByHash to see if it's in mempool
            const userOpResponse = await fetch(bundlerUrl, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    jsonrpc: '2.0',
                    id: 2,
                    method: 'eth_getUserOperationByHash',
                    params: [id],
                }),
            }).then((res) => res.json());
            if (userOpResponse.result) {
                // UserOp exists but no receipt yet - it's pending
                if (telemetry) {
                    logPaymentStatusCheckCompleted({ testnet, status: 'pending', correlationId });
                }
                const result = {
                    status: 'pending',
                    id: id,
                    message: 'Your payment is being processed. This usually takes a few seconds.',
                    sender: userOpResponse.result.sender,
                };
                return result;
            }
            // Not found at all
            if (telemetry) {
                logPaymentStatusCheckCompleted({ testnet, status: 'not_found', correlationId });
            }
            const result = {
                status: 'not_found',
                id: id,
                message: 'Payment not found. Please check your transaction ID.',
            };
            return result;
        }
        // Parse the receipt
        const { success, receipt: txReceipt, reason } = receipt.result;
        // Determine status based on success flag
        if (success) {
            // Parse USDC amount from logs
            let amount;
            let recipient;
            if (txReceipt === null || txReceipt === void 0 ? void 0 : txReceipt.logs) {
                const network = testnet ? 'baseSepolia' : 'base';
                const usdcAddress = TOKENS.USDC.addresses[network].toLowerCase();
                for (const log of txReceipt.logs) {
                    if (((_a = log.address) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === usdcAddress) {
                        try {
                            const decoded = decodeEventLog({
                                abi: ERC20_TRANSFER_ABI,
                                data: log.data,
                                topics: log.topics,
                            });
                            if (decoded.eventName === 'Transfer' && decoded.args) {
                                // The Transfer event has indexed 'from' and 'to', and non-indexed 'value'
                                // viem's decodeEventLog returns indexed args in the args object
                                const args = decoded.args;
                                if (args.value && args.to) {
                                    amount = formatUnits(args.value, 6);
                                    recipient = args.to;
                                    break;
                                }
                            }
                        }
                        catch (e) {
                            console.error('[getPaymentStatus] Error parsing log:', e);
                        }
                    }
                }
            }
            if (telemetry) {
                logPaymentStatusCheckCompleted({ testnet, status: 'completed', correlationId });
            }
            const result = {
                status: 'completed',
                id: id,
                message: 'Payment completed successfully',
                sender: receipt.result.sender,
                amount,
                recipient,
            };
            return result;
        }
        else {
            // Parse a user-friendly reason for failure
            let userFriendlyReason = 'Payment could not be completed';
            if (reason) {
                if (reason.toLowerCase().includes('insufficient')) {
                    userFriendlyReason = 'Insufficient USDC balance';
                }
                else {
                    userFriendlyReason = reason;
                }
            }
            if (telemetry) {
                logPaymentStatusCheckCompleted({ testnet, status: 'failed', correlationId });
            }
            const result = {
                status: 'failed',
                id: id,
                message: 'Payment failed',
                sender: receipt.result.sender,
                reason: userFriendlyReason,
            };
            return result;
        }
    }
    catch (error) {
        console.error('[getPaymentStatus] Error checking status:', error);
        const errorMessage = error instanceof Error ? error.message : 'Connection error';
        if (telemetry) {
            logPaymentStatusCheckError({ testnet, correlationId, errorMessage });
        }
        // Re-throw the error
        throw error;
    }
}
//# sourceMappingURL=getPaymentStatus.js.map