/**
 * test-x402.ts — End-to-end x402 payment test against rSpace rSplat.
 *
 * Tests the full 402 flow:
 *   1. POST to the gated endpoint → expect 402 with payment requirements
 *   2. Sign USDC payment on Base Sepolia using EIP-3009
 *   3. Retry with X-PAYMENT header → expect 200/201
 *
 * Usage:
 *   EVM_PRIVATE_KEY=0x... bun run scripts/test-x402.ts [url]
 *
 * Defaults to https://demo.rspace.online/rsplat/api/splats
 * Wallet needs testnet USDC from https://faucet.circle.com
 */

import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";

const PRIVATE_KEY = process.env.EVM_PRIVATE_KEY as `0x${string}`;
if (!PRIVATE_KEY) {
	console.error("Set EVM_PRIVATE_KEY env var (0x-prefixed hex private key)");
	process.exit(1);
}

const TARGET_URL =
	process.argv[2] || "https://demo.rspace.online/api/x402-test";

async function main() {
	console.log("=== x402 Payment Test ===\n");
	console.log("Target:", TARGET_URL);

	// Step 1: Verify the endpoint returns 402
	console.log("\n[1] Testing 402 response (no payment)...");
	const raw = await fetch(TARGET_URL, { method: "POST" });
	console.log("  Status:", raw.status);

	if (raw.status !== 402) {
		console.log("  Expected 402, got", raw.status);
		console.log("  Body:", await raw.text());
		process.exit(1);
	}

	const body = (await raw.json()) as {
		paymentRequirements?: {
			payTo: string;
			network: string;
			maxAmountRequired: string;
		};
	};
	console.log("  Payment requirements:");
	console.log("    payTo:", body.paymentRequirements?.payTo);
	console.log("    network:", body.paymentRequirements?.network);
	console.log("    amount:", body.paymentRequirements?.maxAmountRequired);

	// Step 2: Set up x402 client with EVM signer
	console.log("\n[2] Setting up x402 client...");
	const account = privateKeyToAccount(PRIVATE_KEY);
	console.log("  Wallet:", account.address);

	const client = new x402Client();
	client.register("eip155:84532", new ExactEvmScheme(account as any));

	const paidFetch = wrapFetchWithPayment(fetch, client);

	// Step 3: Make the paid request
	console.log("\n[3] Making paid request (x402 client handles signing automatically)...");

	try {
		const res = await paidFetch(TARGET_URL, {
			method: "POST",
			headers: { "Content-Type": "application/json" },
			body: JSON.stringify({ test: true }),
		});

		console.log("  Status:", res.status);
		const resBody = await res.text();
		try {
			console.log(
				"  Response:",
				JSON.stringify(JSON.parse(resBody), null, 2),
			);
		} catch {
			console.log("  Response:", resBody.slice(0, 500));
		}

		if (res.ok) {
			console.log("\n  x402 payment successful! USDC transferred on Base Sepolia.");
		} else if (res.status === 402) {
			console.log("\n  Still 402 — payment signing or verification failed.");
			console.log(
				"  Check wallet has USDC on Base Sepolia (faucet: https://faucet.circle.com)",
			);
		}
	} catch (err) {
		console.error("  Error:", err);
	}
}

main();
