/**
 * GET /api/x402/trust/street-cred?address=0x...
 *
 * x402 payment-gated lookup — $0.02 USDC per query.
 *
 * Resolves the canonical Vaultfire Street Cred profile for any address by
 * calling VaultfireStreetCred.computeScore(address) on Base. The contract is
 * the single source of truth — no formula drift between Solidity and TS.
 *
 * Returns: score (0-95), tier (0-4), tierName (None/Bronze/Silver/Gold/Platinum),
 * registered, hasBond, bondActive, bondCount, stakeWei, stakeEth, hasBadge.
 *
 * Base-only — VaultfireStreetCred is deployed only on Base mainnet.
 */

import { NextRequest, NextResponse } from 'next/server';
import { withX402MultiNet } from '../_lib/with-x402-multinet';
import { ethers } from 'ethers';
import { withFailover } from '../../../_lib/rpc-retry';

const STREET_CRED_ADDRESS = '0x5CfAB4B12718549e156D3642f9C63476aC4c2f99';

const TIER_NAMES: Record<number, string> = {
  0: 'None',
  1: 'Bronze',
  2: 'Silver',
  3: 'Gold',
  4: 'Platinum',
};

// Canonical ABI fragment — same as app/api/_lib/erc8128.ts (single source of truth)
const STREET_CRED_ABI = [
  'function computeScore(address agent) view returns (uint16 score, uint8 tier, bool registered, bool hasBond, bool bondActive, uint256 bondCount, uint256 stakeWei)',
  'function scoreOf(address agent) view returns (uint256)',
  'function tierOf(address agent) view returns (uint8)',
  'function totalMinted() view returns (uint256)',
] as const;

const handler = async (req: NextRequest) => {
  const { searchParams } = req.nextUrl;
  const address = searchParams.get('address');

  if (!address) {
    return NextResponse.json({ error: 'address query parameter is required' }, { status: 400 });
  }
  if (!ethers.isAddress(address)) {
    return NextResponse.json({ error: 'Invalid address' }, { status: 400 });
  }

  try {
    const { score, tier, registered, hasBond, bondActive, bondCount, stakeWei, hasBadge } = await withFailover('base', async (provider) => {
      const c = new ethers.Contract(STREET_CRED_ADDRESS, STREET_CRED_ABI, provider);
      // Single canonical call resolves everything (matches erc8128.ts pattern)
      const result = await c.computeScore(address);
      const tierNum = Number(result[1]);
      // Probe scoreOf separately as a sanity check (returns 0 cleanly for non-holders)
      const onchainScore = await c.scoreOf(address);
      return {
        score: Number(result[0]),
        tier: tierNum,
        registered: Boolean(result[2]),
        hasBond: Boolean(result[3]),
        bondActive: Boolean(result[4]),
        bondCount: Number(result[5]),
        stakeWei: BigInt(result[6]),
        hasBadge: Number(onchainScore) > 0 || tierNum > 0,
      };
    });

    return NextResponse.json({
      address: address.toLowerCase(),
      chain: 'base',
      contractAddress: STREET_CRED_ADDRESS,
      score,
      tier,
      tierName: TIER_NAMES[tier] ?? 'Unknown',
      maxScore: 95,
      thresholds: { Bronze: '1-30', Silver: '31-55', Gold: '56-75', Platinum: '76-95' },
      identity: { registered },
      bond: { hasBond, bondActive, bondCount, stakeWei: stakeWei.toString(), stakeEth: ethers.formatEther(stakeWei) },
      hasBadge,
      explorerUrl: `https://basescan.org/address/${STREET_CRED_ADDRESS}`,
      _x402: {
        paid: true,
        price: '$0.02 USDC',
        service: 'vaultfire-trust',
        facilitator: 'cdp',
      },
    }, {
      headers: {
        'Access-Control-Allow-Origin': '*',
        'Cache-Control': 'no-store',
      },
    });
  } catch (e: any) {
    return NextResponse.json(
      { error: 'Failed to query VaultfireStreetCred contract', detail: e?.shortMessage || e?.message || String(e) },
      { status: 502 }
    );
  }
};

// Multi-network paywall: accepts USDC on Base AND Solana mainnet.
// Bazaar discovery picks up both networks from the 402 response's `accepts` array.
export const GET = withX402MultiNet(handler, {
  price: '$0.02',
  description: "Vaultfire — the trust layer for the agentic web. 72 x402 endpoints on Base for AI agent identity (ERC-8004), accountability bonds, on-chain reputation, and Chainlink oracle data. — This endpoint: look up any address's Vaultfire Street Cred profile (soulbound badge tier None/Bronze/Silver/Gold/Platinum, score 0-95, identity registration, active bonds, staked ETH). Reads VaultfireStreetCred.computeScore() on Base — the on-chain contract is the single source of truth.",
      mimeType: 'application/json',
      outputSchema: {
        type: 'object',
        properties: {
          address: { type: 'string', description: 'Agent wallet address' },
          chain: { type: 'string', description: 'Always "base" — Street Cred is Base-only' },
          contractAddress: { type: 'string', description: 'VaultfireStreetCred contract address on Base' },
          score: { type: 'number', description: 'Street Cred score 0-95' },
          tier: { type: 'number', description: 'Tier number 0-4' },
          tierName: { type: 'string', description: 'Tier name: None / Bronze / Silver / Gold / Platinum' },
          maxScore: { type: 'number' },
          thresholds: { type: 'object', description: 'Score-to-tier thresholds' },
          identity: { type: 'object', description: '{ registered: boolean }' },
          bond: { type: 'object', description: '{ hasBond, bondActive, bondCount, stakeWei, stakeEth }' },
          hasBadge: { type: 'boolean', description: 'True if address holds a soulbound Street Cred badge' },
          explorerUrl: { type: 'string', description: 'BaseScan link to the contract' },
        },
      }
}) as (req: NextRequest) => Promise<Response>;
