/**
 * GET /api/x402/trust/risk-score
 *
 * x402 payment-gated composite risk score — $0.02 USDC per query.
 * Combines bonds, vouches, slashes, age, and trust score into a single
 * 0–100 risk score (higher = riskier).
 *
 * Query:
 *   ?address=0x...   — required
 *   ?chain=base      — default base
 */

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

function band(risk: number): string {
  if (risk >= 75) return 'high';
  if (risk >= 45) return 'medium';
  if (risk >= 20) return 'low';
  return 'minimal';
}

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

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

  try {
    const [statusRes, vouchRes] = await Promise.all([
      fetch(`${req.nextUrl.origin}/api/agent/status?address=${encodeURIComponent(address)}&chain=${chain}`, { signal: AbortSignal.timeout(15000) }).then(r => r.json()).catch(() => ({})),
      fetch(`${req.nextUrl.origin}/api/agent/vouching?address=${encodeURIComponent(address)}&chain=${chain}`, { signal: AbortSignal.timeout(15000) }).then(r => r.json()).catch(() => ({})),
    ]);

    const registered = !!statusRes?.registered;
    const trustScore = statusRes?.trustScore || 0;          // 0–95 range
    const bondCount = statusRes?.bondCount || 0;
    const registeredAt = statusRes?.registeredAt || 0;
    const vouchesReceived = parseInt(vouchRes?.profile?.totalVouchesReceived || '0', 10);
    const slashCount = parseInt(vouchRes?.profile?.slashCount || '0', 10);

    // Components (each 0–100, higher = riskier)
    const components: Record<string, { score: number; weight: number; reason: string }> = {};

    // Identity: unregistered = max risk
    components.identity = {
      score: registered ? 0 : 100,
      weight: 0.25,
      reason: registered ? 'ERC-8004 registered' : 'NOT registered on-chain',
    };

    // Trust score: invert (higher trust = lower risk). Trust is 0–95.
    components.reputation = {
      score: Math.max(0, 100 - Math.round((trustScore / 95) * 100)),
      weight: 0.25,
      reason: `Trust score ${trustScore}/95`,
    };

    // Bonds: 0 bonds is riskier; cap risk reduction at 5 bonds
    const bondRisk = bondCount === 0 ? 70 : Math.max(0, 50 - bondCount * 10);
    components.bonds = {
      score: bondRisk,
      weight: 0.20,
      reason: `${bondCount} active bonds`,
    };

    // Vouching: receiving vouches reduces risk; slashes increase it sharply
    const vouchRisk = vouchesReceived === 0 ? 60 : Math.max(0, 40 - vouchesReceived * 8);
    const slashPenalty = Math.min(60, slashCount * 30);
    components.vouching = {
      score: Math.min(100, vouchRisk + slashPenalty),
      weight: 0.20,
      reason: `${vouchesReceived} vouches, ${slashCount} slashes`,
    };

    // Age: agents registered <30 days are mildly riskier
    const now = Math.floor(Date.now() / 1000);
    const ageSec = registeredAt > 0 ? now - registeredAt : 0;
    const ageDays = ageSec / 86400;
    const ageRisk = !registered ? 100 : ageDays < 7 ? 60 : ageDays < 30 ? 30 : ageDays < 90 ? 10 : 0;
    components.age = {
      score: ageRisk,
      weight: 0.10,
      reason: registered ? `${Math.round(ageDays)} days old` : 'unregistered',
    };

    const composite = Math.round(
      Object.values(components).reduce((sum, c) => sum + c.score * c.weight, 0)
    );

    return NextResponse.json({
      address,
      chain,
      riskScore: composite,
      band: band(composite),
      components,
      inputs: {
        registered,
        trustScore,
        bondCount,
        vouchesReceived,
        slashCount,
        ageDays: Math.round(ageDays),
      },
      _x402: {
        paid: true,
        price: '$0.02 USDC',
        service: 'vaultfire-trust',
        facilitator: 'cdp',
      },
    }, {
      headers: {
        'Access-Control-Allow-Origin': '*',
        'Cache-Control': 'no-store',
      },
    });
  } catch {
    return NextResponse.json(
      { error: 'Failed to query Vaultfire hub' },
      { 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: 'Composite on-chain risk score (0–100) for an AI agent — combines identity, reputation, bonds, vouching, slashes, and account age into a single risk signal with band (minimal/low/medium/high).',
      mimeType: 'application/json',
      outputSchema: {
        type: 'object',
        properties: {
          address: { type: 'string' },
          chain: { type: 'string' },
          riskScore: { type: 'number', description: '0–100, higher = riskier' },
          band: { type: 'string', description: 'minimal | low | medium | high' },
          components: { type: 'object' },
          inputs: { type: 'object' },
        },
      }
}) as (req: NextRequest) => Promise<Response>;
