/**
 * GET /api/x402/oracle/price-feed?pair=eth-usd&chain=base — $0.01 USDC
 *
 * Reads a Chainlink Data Feed via AggregatorV3Interface.latestRoundData().
 * Vaultfire does not operate the feed — Chainlink's decentralized oracle
 * network is the source of truth. This endpoint exposes Chainlink feeds
 * to x402-paying agents on Base + Solana, with RPC failover and 4-chain coverage.
 *
 * Supported pairs:
 *   eth-usd   — on base, avalanche, arbitrum, polygon
 *   btc-usd   — on base, avalanche, arbitrum, polygon
 *   usdc-usd  — on base
 *   link-usd  — on base, avalanche, arbitrum, polygon
 *   avax-usd  — on avalanche
 *   matic-usd — on polygon
 *
 * Returns: answer (human + raw), decimals, roundId, updatedAt, ageSeconds,
 * fresh (boolean — true if updated within last 24h), feedAddress, explorerUrl.
 */

import { NextRequest, NextResponse } from 'next/server';
import { ethers } from 'ethers';
import { withX402 } from 'x402-next';
import { facilitator } from '@coinbase/x402';
import { withFailover } from '../../../_lib/rpc-retry';
import { FEEDS, AGGREGATOR_V3_ABI, SUPPORTED_CHAINS, SUPPORTED_PAIRS, type ChainKey, type PairKey } from '../_lib/feeds';

const PAY_TO = '0xfA15Ee28939B222B0448261A22156070f0A7813C';

// 24h freshness threshold — Chainlink "heartbeat" varies per feed but is
// always well under 24h, so anything older than this is definitively stale.
const FRESH_THRESHOLD_SECONDS = 86400;

const handler = async (req: NextRequest) => {
  const { searchParams } = req.nextUrl;
  const pair = (searchParams.get('pair') || '').toLowerCase() as PairKey;
  const chain = (searchParams.get('chain') || 'base').toLowerCase() as ChainKey;

  if (!pair) {
    return NextResponse.json(
      { error: `pair query parameter is required. Supported: ${SUPPORTED_PAIRS.join(', ')}` },
      { status: 400 },
    );
  }
  if (!SUPPORTED_PAIRS.includes(pair)) {
    return NextResponse.json(
      { error: `Invalid pair. Supported: ${SUPPORTED_PAIRS.join(', ')}` },
      { status: 400 },
    );
  }
  if (!SUPPORTED_CHAINS.includes(chain)) {
    return NextResponse.json(
      { error: `Invalid chain. Supported: ${SUPPORTED_CHAINS.join(', ')}` },
      { status: 400 },
    );
  }

  const feed = FEEDS[chain][pair];
  if (!feed) {
    return NextResponse.json(
      { error: `Pair '${pair}' is not available on chain '${chain}'. See /api/x402/oracle/chainlink-status for the support matrix.` },
      { status: 404 },
    );
  }

  try {
    const roundData = await withFailover(chain, async (provider) => {
      const c = new ethers.Contract(feed.address, AGGREGATOR_V3_ABI, provider);
      return (await c.latestRoundData()) as [bigint, bigint, bigint, bigint, bigint];
    });

    const [roundId, answerRaw, startedAt, updatedAt] = roundData;
    const nowSec = Math.floor(Date.now() / 1000);
    const ageSeconds = nowSec - Number(updatedAt);
    const answerNumber = Number(answerRaw) / 10 ** feed.decimals;

    return NextResponse.json({
      pair,
      chain,
      source: 'chainlink',
      feedAddress: feed.address,
      explorerUrl: feed.explorerUrl,
      answer: answerNumber,
      answerRaw: answerRaw.toString(),
      decimals: feed.decimals,
      roundId: roundId.toString(),
      startedAt: Number(startedAt),
      updatedAt: Number(updatedAt),
      ageSeconds,
      fresh: ageSeconds >= 0 && ageSeconds < FRESH_THRESHOLD_SECONDS,
      ...(feed.note ? { note: feed.note } : {}),
      _x402: { paid: true, price: '$0.01 USDC', service: 'vaultfire-oracle', facilitator: 'cdp' },
      _attribution: 'Price data provided by Chainlink (https://chain.link). Vaultfire reads the Chainlink AggregatorV3 proxy contract on-chain and exposes it via x402 for agent consumption.',
    }, { headers: { 'Access-Control-Allow-Origin': '*', 'Cache-Control': 'no-store' } });
  } catch (e) {
    const err = e as { shortMessage?: string; message?: string };
    return NextResponse.json(
      { error: 'Failed to read Chainlink price feed', detail: err?.shortMessage || err?.message || String(e) },
      { status: 502 },
    );
  }
};

// Canonical CDP paywall (matches actions/* family) — triggers CDP catalog auto-ingest.
export const GET = withX402(handler as (req: NextRequest) => Promise<NextResponse>, PAY_TO, {
  price: '$0.01', network: 'base',
  config: {
    description: 'Read any supported Chainlink Data Feed (ETH/USD, BTC/USD, LINK/USD, USDC/USD, AVAX/USD, MATIC/USD) on Base, Avalanche, Arbitrum, or Polygon. Returns answer, decimals, roundId, updatedAt, and freshness status. Data source: Chainlink decentralized oracle network — Vaultfire reads the on-chain AggregatorV3 proxy and exposes it via x402.',
    mimeType: 'application/json',
    outputSchema: {
      input: { type: 'http', method: 'GET', discoverable: true,
        queryParams: {
          pair: { type: 'string', description: 'Price pair: eth-usd | btc-usd | link-usd | usdc-usd | avax-usd | matic-usd' },
          chain: { type: 'string', description: 'Chain: base | avalanche | arbitrum | polygon (default: base)' },
        },
      },
      output: {
        type: 'object',
        properties: {
          pair: { type: 'string' },
          chain: { type: 'string' },
          source: { type: 'string' },
          feedAddress: { type: 'string' },
          explorerUrl: { type: 'string' },
          answer: { type: 'number' },
          answerRaw: { type: 'string' },
          decimals: { type: 'number' },
          roundId: { type: 'string' },
          startedAt: { type: 'number' },
          updatedAt: { type: 'number' },
          ageSeconds: { type: 'number' },
          fresh: { type: 'boolean' },
        },
      },
    },
  },
}, facilitator);

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