/**
 * GET /api/admin/recent-payers
 *
 * Token-gated admin readback of the payer-attribution log. Returns the most
 * recent paid x402 calls with full payer addresses, paths, prices, chains,
 * and freshness/heartbeat status.
 *
 * Auth:
 *   Header `x-admin-token: <ADMIN_TOKEN env>` (preferred)
 * *
 *   When ADMIN_TOKEN is unset, requests are rejected (fail-closed). This
 *   prevents accidental exposure of full payer addresses if the env var
 *   is dropped during a redeploy.
 *
 * Query params:
 *   limit  number of recent calls to return (1\u2013500, default 100)
 *
 * No PII in any response — only public on-chain data already visible in
 * Vercel logs and on BaseScan/Solana explorers.
 */

import { NextRequest, NextResponse } from 'next/server';
import {
  getRecentPaidCalls,
  getPathCounts,
  getLifetimeTotals,
  readHeartbeat,
  isPersistenceConfigured,
} from '../../_lib/payer-log';

export const dynamic = 'force-dynamic';
export const revalidate = 0;

const HEARTBEAT_HEALTHY_MS = 120_000; // 2 minutes

export async function GET(req: NextRequest): Promise<NextResponse> {
  const adminToken = process.env.ADMIN_TOKEN;
  if (!adminToken) {
    // Fail closed when the gate is missing. Better to 503 the dashboard than
    // accidentally serve full payer addresses publicly.
    return NextResponse.json(
      { error: 'ADMIN_TOKEN not configured on server' },
      { status: 503 },
    );
  }

  const provided = req.headers.get('x-admin-token');
  if (provided !== adminToken) {
    return NextResponse.json({ error: 'unauthorized' }, { status: 401 });
  }

  const limitRaw = parseInt(req.nextUrl.searchParams.get('limit') || '100', 10);
  const limit = Math.min(Math.max(Number.isFinite(limitRaw) ? limitRaw : 100, 1), 500);

  if (!isPersistenceConfigured()) {
    return NextResponse.json(
      {
        configured: false,
        message:
          'KV persistence not configured. Set KV_REST_API_URL + KV_REST_API_TOKEN ' +
          'in the Vercel project env. Until then, payer-log is a no-op.',
        recent: [],
        pathCounts: {},
        lifetime: { calls: 0, usdcMicro: 0, usdc: '0' },
        heartbeat: { lastMs: null, ageMs: null, healthy: false },
      },
      { status: 200, headers: { 'Cache-Control': 'no-store' } },
    );
  }

  // Fan out reads in parallel.
  const [recent, pathCounts, lifetime, heartbeat] = await Promise.all([
    getRecentPaidCalls(limit),
    getPathCounts(),
    getLifetimeTotals(),
    readHeartbeat(),
  ]);

  const heartbeatAgeMs = heartbeat ? Date.now() - heartbeat : null;
  const heartbeatHealthy = heartbeatAgeMs !== null && heartbeatAgeMs < HEARTBEAT_HEALTHY_MS;

  return NextResponse.json(
    {
      configured: true,
      generatedAt: new Date().toISOString(),
      heartbeat: {
        lastMs: heartbeat,
        lastIso: heartbeat ? new Date(heartbeat).toISOString() : null,
        ageMs: heartbeatAgeMs,
        healthy: heartbeatHealthy,
        thresholdMs: HEARTBEAT_HEALTHY_MS,
      },
      lifetime: {
        calls: lifetime.calls,
        usdcMicro: lifetime.usdcMicro,
        usdc: (lifetime.usdcMicro / 1_000_000).toFixed(6),
      },
      pathCounts,
      recent,
      recentCount: recent.length,
    },
    { status: 200, headers: { 'Cache-Control': 'no-store' } },
  );
}
