// End-to-end test for the test-mpp service on the relay.
//
// Fill in the CONFIG block, then run from the isolated install dir
// (same workaround as tempo-transfer.ts — repo node_modules has a
// @noble/hashes conflict that breaks viem here):
//
//   mkdir -p /tmp/tempo-transfer && cd /tmp/tempo-transfer \
//     && npm init -y && npm install viem@2.47.6 mppx tsx
//   /tmp/tempo-transfer/node_modules/.bin/tsx scripts/test-mpp-call.ts
//
// What it does:
//   1. Reads on-chain USDC balance for the bot wallet on Tempo.
//   2. POSTs to /api/services/test-mpp/use through the mppx client,
//      which auto-handles the 402 → sign USDC transfer → retry flow.
//   3. Prints status, body, Payment-Receipt header, and the new balance.
//
// Expected first-run output (with $0 account balance, $1 wallet):
//   paidVia=mpp · balance drops by $0.01 · Payment-Receipt header present.

// ─── CONFIG ──────────────────────────────────────────────────────────────────

const RELAY = 'https://api.bloby.bot';

const BOT = {
  // Bot's relay token — the value from `bloby init` / config.json `relay.token`.
  // Used as `X-Bloby-Token` header so identity survives the mppx 402 retry.
  relayToken: '<FILL_ME — 64-hex-char relay token>',

  // Bot's USDC wallet on Tempo. Must match the `walletAddress` registered
  // with the relay (so account-balance lookups go through the right user).
  privateKey: '0x0a5194196773b67790f0da564337929b842c1c17f9c445b6c449205dbd426a49',
  wallet:     '0xc65d8a0dB80f637337B87e42b8BEb5D86D46f942',
};

// ─────────────────────────────────────────────────────────────────────────────

import { Mppx, tempo } from 'mppx/client';
import { privateKeyToAccount } from 'viem/accounts';
import { createPublicClient, http, formatUnits } from 'viem';
import { tempo as tempoChain } from 'viem/chains';

const USDC = '0x20c000000000000000000000b9537d11c60e8b50' as const;
const RPC = 'https://rpc.tempo.xyz';

const erc20Abi = [{
  name: 'balanceOf',
  type: 'function',
  stateMutability: 'view',
  inputs: [{ name: 'account', type: 'address' }],
  outputs: [{ name: '', type: 'uint256' }],
}] as const;

function normalizePk(pk: string): `0x${string}` {
  const t = pk.trim();
  return (t.startsWith('0x') ? t : `0x${t}`) as `0x${string}`;
}

async function main() {
  if (BOT.relayToken.startsWith('<')) {
    console.error('Fill in BOT.relayToken before running.');
    process.exit(1);
  }

  const account = privateKeyToAccount(normalizePk(BOT.privateKey));
  if (account.address.toLowerCase() !== BOT.wallet.toLowerCase()) {
    console.error(`privateKey derives ${account.address}, but BOT.wallet is ${BOT.wallet}`);
    process.exit(1);
  }

  const publicClient = createPublicClient({ chain: tempoChain, transport: http(RPC) });

  const before = await publicClient.readContract({
    address: USDC, abi: erc20Abi, functionName: 'balanceOf', args: [account.address],
  });
  console.log(`Wallet:        ${account.address}`);
  console.log(`Balance before: ${formatUnits(before, 6)} USDC`);

  // mppx client: do NOT polyfill global fetch — only the request through
  // mppx.fetch(...) gets the auto-pay-on-402 behavior.
  const mppx = Mppx.create({
    polyfill: false,
    methods: [tempo({ account })],
  });

  const url = `${RELAY}/api/services/test-mpp/use`;
  console.log(`POST ${url}`);

  const res = await mppx.fetch(url, {
    method: 'POST',
    headers: {
      'X-Bloby-Token': BOT.relayToken,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({}),
  });

  const body = await res.text();
  const receipt = res.headers.get('Payment-Receipt');

  console.log(`Status:          ${res.status}`);
  console.log(`Body:            ${body}`);
  console.log(`Payment-Receipt: ${receipt ?? '(none — paid via balance or free)'}`);

  const after = await publicClient.readContract({
    address: USDC, abi: erc20Abi, functionName: 'balanceOf', args: [account.address],
  });
  console.log(`Balance after:  ${formatUnits(after, 6)} USDC`);
  const delta = before - after;
  console.log(`Delta:          -${formatUnits(delta, 6)} USDC`);
}

main().catch((err) => {
  console.error(err);
  process.exit(1);
});
