/**
 * POST /api/x402/actions/create-task — $0.30 USDC
 * Calls VaultfireTaskEscrow.createTask(string description, uint256 reward, uint256 deadline)
 * Selector 0x059378ea
 *
 * Tx-prepare ONLY. Caller must first ERC20.approve() USDC to the escrow contract,
 * then sign this tx in their wallet. The escrow contract pulls USDC via transferFrom.
 */
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, TASK_ESCROW, 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, description, rewardUSDC, deadline, chain = 'base' } = body;
  if (!walletAddress || !description || rewardUSDC === undefined || deadline === undefined) {
    return NextResponse.json({ error: 'Missing: walletAddress, description, rewardUSDC, deadline' }, { status: 400 });
  }
  if (!isValidAddress(walletAddress)) return NextResponse.json({ error: 'Invalid walletAddress' }, { status: 400 });
  if (!isValidChain(chain)) return NextResponse.json({ error: 'Invalid chain. Use base|avalanche|arbitrum|polygon' }, { status: 400 });
  if (typeof description !== 'string' || description.length === 0 || description.length > 4096) {
    return NextResponse.json({ error: 'description must be 1-4096 char string' }, { status: 400 });
  }

  // USDC has 6 decimals on all 4 chains
  let rewardWei: bigint;
  try { rewardWei = BigInt(Math.floor(parseFloat(String(rewardUSDC)) * 1_000_000)); } catch { return NextResponse.json({ error: 'Invalid rewardUSDC' }, { status: 400 }); }
  if (rewardWei <= 0n) return NextResponse.json({ error: 'rewardUSDC must be > 0' }, { status: 400 });

  let deadlineTs: bigint;
  try { deadlineTs = BigInt(deadline); } catch { return NextResponse.json({ error: 'Invalid deadline (unix seconds)' }, { status: 400 }); }
  const now = BigInt(Math.floor(Date.now() / 1000));
  if (deadlineTs <= now) return NextResponse.json({ error: 'deadline must be a future unix timestamp (seconds)' }, { status: 400 });

  // ABI-encode createTask(string,uint256,uint256):
  //   head[0] = offset to string = 0x60 (3 head words × 32 bytes)
  //   head[1] = reward
  //   head[2] = deadline
  //   tail   = dynamic string (length + utf8 padded)
  const calldata = '0x059378ea'
    + encodeUint256(0x60)
    + encodeUint256(rewardWei)
    + encodeUint256(deadlineTs)
    + encodeString(description);

  const contract = TASK_ESCROW[chain];
  const gasEstimate = await estimateGas(RPC_URLS[chain], walletAddress, contract, calldata);

  return NextResponse.json({
    success: true,
    txData: { to: contract, data: calldata, value: '0', chainId: CHAIN_IDS[chain], gasEstimate },
    chain,
    explorer: `${EXPLORERS[chain]}/address/${contract}`,
    rewardUSDC: Number(rewardWei) / 1_000_000,
    deadline: deadlineTs.toString(),
    note: 'Approve USDC spending on the escrow contract BEFORE signing this tx. Escrow pulls USDC via transferFrom.',
    message: `Sign to post a task with ${Number(rewardWei) / 1_000_000} USDC escrow on Vaultfire (${chain}).`,
    securityNote: 'Vaultfire NEVER accepts private keys. Trustless USDC escrow with 1% protocol fee.',
    _x402: { paid: true, price: '$0.30 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.30', '/actions/create-task'), PAY_TO, {
  price: '$0.30', network: 'base',
  config: {
    description: 'Post a task with USDC escrow on VaultfireTaskEscrow. Pay $0.30 USDC, sign in your wallet — funds locked trustlessly until an agent completes the task. 1% protocol fee, refunded if cancelled. Multi-chain (Base, Avalanche, Arbitrum, Polygon).',
    mimeType: 'application/json',
    outputSchema: {
      input: { type: 'http', method: 'POST', discoverable: true,
        bodySchema: {
          type: 'object', required: ['walletAddress', 'description', 'rewardUSDC', 'deadline'],
          properties: {
            walletAddress: { type: 'string', description: 'Requester wallet that funds and signs' },
            description: { type: 'string', description: 'Plain-text task description (1-4096 chars)' },
            rewardUSDC: { type: 'string', description: 'USDC reward (e.g. "10.5" for 10.5 USDC)' },
            deadline: { type: 'string', description: 'Unix timestamp (seconds) for completion deadline' },
            chain: { type: 'string', enum: ['base', 'avalanche', 'arbitrum', 'polygon'] },
          },
        },
      },
      output: { type: 'object', properties: { success: { type: 'boolean' }, txData: { type: 'object' }, chain: { type: 'string' }, rewardUSDC: { type: 'number' }, deadline: { 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' } });
}
