/**
 * POST /api/x402/actions/update-agent-uri
 *
 * x402 payment-gated tx-prepare for ERC-8004 agentURI update — $0.10 USDC.
 *
 * Returns an unsigned transaction the caller signs in their own wallet.
 * NO private keys are ever accepted server-side. The wallet that signs MUST
 * be the registered agent (contract uses msg.sender to look up the record).
 *
 * Body (JSON):
 *   - walletAddress: string (must be the registered agent)
 *   - newAgentURI: string (new metadata URI or JSON string)
 *   - chain?: "base" | "avalanche" | "arbitrum" | "polygon" (default: "base")
 *
 * Returns:
 *   txData: { to, data, value, chainId, gasEstimate } — sign in your wallet.
 */

import { NextRequest, NextResponse } from 'next/server';
import { withX402 } from 'x402-next';
import { facilitator } from '@coinbase/x402';
import { withActionLogging } from '../_lib/log-action';
import {
  CHAIN_IDS, RPC_URLS, EXPLORERS, IDENTITY_REGISTRY, SUPPORTED_CHAINS,
  isValidAddress, isValidChain, encodeUint256, encodeString,
  estimateGas, rejectsPrivateKeyShape,
} from '../_lib/tx-encode';

const PAY_TO = '0xfA15Ee28939B222B0448261A22156070f0A7813C';

const handler = async (req: NextRequest) => {
  let body: any;
  try { body = await req.json(); } catch { body = {}; }

  const keyErr = rejectsPrivateKeyShape(body);
  if (keyErr) return NextResponse.json({ error: keyErr }, { status: 400 });

  const { walletAddress, newAgentURI, chain = 'base' } = body;

  if (!walletAddress || !newAgentURI) {
    return NextResponse.json({ error: 'Missing required fields: walletAddress, newAgentURI' }, { status: 400 });
  }
  if (!isValidAddress(walletAddress)) {
    return NextResponse.json({ error: 'Invalid walletAddress' }, { status: 400 });
  }
  if (!isValidChain(chain)) {
    return NextResponse.json({ error: `Invalid chain. Use: ${SUPPORTED_CHAINS.join(', ')}` }, { status: 400 });
  }
  const uri = String(newAgentURI);
  if (uri.length < 1 || uri.length > 4096) {
    return NextResponse.json({ error: 'newAgentURI must be 1-4096 chars' }, { status: 400 });
  }

  // Calldata for updateAgentURI(string) — selector 0x9f34dace
  const uriEncoded = encodeString(uri);
  const calldata = '0x9f34dace' + encodeUint256(0x20) + uriEncoded;

  const registry = IDENTITY_REGISTRY[chain];
  const rpc = RPC_URLS[chain];
  const chainId = CHAIN_IDS[chain];
  const gasEstimate = await estimateGas(rpc, walletAddress, registry, calldata);

  return NextResponse.json({
    success: true,
    txData: {
      to: registry,
      data: calldata,
      value: '0',
      chainId,
      gasEstimate,
    },
    chain,
    explorer: `${EXPLORERS[chain]}/address/${registry}`,
    message: `Sign this transaction in your wallet (${walletAddress}) to update the agentURI on ${chain}. Your wallet must already be the registered agent.`,
    securityNote: 'Vaultfire NEVER accepts private keys. Sign locally in your Base App / MetaMask / WalletConnect.',
    _x402: {
      paid: true,
      price: '$0.10 USDC',
      service: 'vaultfire-trust',
      facilitator: 'cdp',
      pattern: 'tx-prepare (caller signs)',
    },
  }, { headers: { 'Access-Control-Allow-Origin': '*', 'Cache-Control': 'no-store' } });
};

export const POST = withX402(
  withActionLogging(handler, '$0.10', '/actions/update-agent-uri'),
  PAY_TO,
  {
    price: '$0.10',
    network: 'base',
    config: {
      description: 'Update the agentURI of a registered ERC-8004 agent. Pay $0.10 in USDC and receive an unsigned transaction — sign locally in your wallet (which must be the registered agent). No private keys touch our servers.',
      mimeType: 'application/json',
      outputSchema: {
        input: {
          type: 'http',
          method: 'POST',
          discoverable: true,
          bodySchema: {
            type: 'object',
            required: ['walletAddress', 'newAgentURI'],
            properties: {
              walletAddress: { type: 'string', description: 'Registered agent address that will sign' },
              newAgentURI: { type: 'string', description: 'New metadata URI (1-4096 chars)' },
              chain: { type: 'string', enum: ['base', 'avalanche', 'arbitrum', 'polygon'] },
            },
          },
        },
        output: {
          type: 'object',
          properties: {
            success: { type: 'boolean' },
            txData: { type: 'object' },
            chain: { type: 'string' },
            explorer: { type: 'string' },
            message: { type: 'string' },
          },
        },
      },
    },
  },
  facilitator,
);

export async function OPTIONS() {
  return new NextResponse(null, {
    status: 204,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'POST, OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type',
    },
  });
}
