/**
 * GET /api/hub/stats
 *
 * Get current Agent Hub statistics — live from Base, Avalanche, Arbitrum, and Polygon.
 * No hardcoded data. Every number comes from the blockchain.
 *
 * Uses verified selectors:
 *   getTotalAgents() → 0x3731a16f
 *   nextBondId()     → 0xee53a423
 */

import { NextResponse } from 'next/server';

/* ── CORS headers ── */
const CORS_HEADERS = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Methods': 'GET, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type',
};

export async function OPTIONS() {
  return new NextResponse(null, { status: 204, headers: CORS_HEADERS });
}

// One identity registry per chain — source of truth from contracts.ts.
// Only count the CURRENT official registries. No old/duplicate deployments.
const CHAINS = {
  base: {
    rpcs: ['https://base-rpc.publicnode.com', 'https://mainnet.base.org'],
    identities: ['0xa7BD20bf5De63df949cA5Be2F20835978eCba81A'],
    partnership: '0x01C479F0c039fEC40c0Cf1c5C921bab457d57441',
    accountability: '0x6750D28865434344e04e1D0a6044394b726C3dfE',
  },
  avalanche: {
    rpcs: ['https://api.avax.network/ext/bc/C/rpc', 'https://avalanche-c-chain-rpc.publicnode.com'],
    identities: ['0x7448057C95Fb8a8B974a566cdcc9Cd042166A3f8'],
    partnership: '0xDC8447c66fE9D9c7D54607A98346A15324b7985D',
    accountability: '0x376831fB2457E34559891c32bEb61c442053C066',
  },
  arbitrum: {
    rpcs: ['https://arb1.arbitrum.io/rpc', 'https://arbitrum-one-rpc.publicnode.com'],
    identities: ['0x83dd216449B3F0574E39043ECFE275946fa492e9'],
    partnership: '0xdB54B8925664816187646174bdBb6Ac658A55a5F',
    accountability: '0xef3A944f4d7bb376699C83A29d7Cb42C90D9B6F0',
  },
  polygon: {
    rpcs: ['https://polygon-bor-rpc.publicnode.com'],
    identities: ['0xD9bF6D92a1D9ee44a48c38481c046a819CBdf2ba'],
    partnership: '0x83dd216449B3F0574E39043ECFE275946fa492e9',
    accountability: '0xdB54B8925664816187646174bdBb6Ac658A55a5F',
  },
} as const;

type ChainKey = keyof typeof CHAINS;

async function rpcCallOne(rpcUrl: string, method: string, params: unknown[]) {
  const res = await fetch(rpcUrl, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ jsonrpc: '2.0', id: Date.now(), method, params }),
    signal: AbortSignal.timeout(12000),
  });
  return res.json();
}

/** Try each RPC in order; returns first successful JSON-RPC response (with .result). */
async function rpcCall(rpcs: readonly string[], method: string, params: unknown[]): Promise<any> {
  let lastError: any = null;
  for (const url of rpcs) {
    try {
      const json = await rpcCallOne(url, method, params);
      if (json && json.result && !json.error) return json;
      lastError = json?.error ?? { message: 'empty result' };
    } catch (e) {
      lastError = e;
    }
  }
  return { error: lastError };
}

async function getAgentCount(chain: ChainKey): Promise<number> {
  let total = 0;
  for (const addr of CHAINS[chain].identities) {
    try {
      const result = await rpcCall(CHAINS[chain].rpcs, 'eth_call', [
        { to: addr, data: '0x3731a16f' }, // getTotalAgents()
        'latest',
      ]);
      if (result.result && !result.error) {
        total += parseInt(result.result, 16);
      }
    } catch {
      // skip failed calls
    }
  }
  return total;
}

async function getBondCount(chain: ChainKey, contract: 'partnership' | 'accountability'): Promise<number> {
  try {
    const result = await rpcCall(CHAINS[chain].rpcs, 'eth_call', [
      { to: CHAINS[chain][contract], data: '0xee53a423' }, // nextBondId()
      'latest',
    ]);
    if (!result.result || result.error) return 0;
    const nextId = parseInt(result.result, 16);
    return Math.max(0, nextId - 1); // bonds start at 1
  } catch {
    return 0;
  }
}

async function getBondBalance(chain: ChainKey): Promise<number> {
  try {
    const [acctResult, partnerResult] = await Promise.allSettled([
      rpcCall(CHAINS[chain].rpcs, 'eth_call', [
        { to: CHAINS[chain].accountability, data: '0xe7683e58' }, // totalActiveBondValue()
        'latest',
      ]),
      rpcCall(CHAINS[chain].rpcs, 'eth_call', [
        { to: CHAINS[chain].partnership, data: '0xe7683e58' }, // totalActiveBondValue()
        'latest',
      ]),
    ]);
    let total = 0;
    if (acctResult.status === 'fulfilled' && acctResult.value.result && !acctResult.value.error) {
      total += Number(BigInt(acctResult.value.result)) / 1e18;
    }
    if (partnerResult.status === 'fulfilled' && partnerResult.value.result && !partnerResult.value.error) {
      total += Number(BigInt(partnerResult.value.result)) / 1e18;
    }
    return Math.round(total * 1e6) / 1e6;
  } catch {
    return 0;
  }
}

// Cache stats for 60 seconds
let statsCache: { data: Record<string, unknown>; ts: number } | null = null;
const CACHE_TTL = 60_000;

export async function GET() {
  try {
    if (statsCache && Date.now() - statsCache.ts < CACHE_TTL) {
      return NextResponse.json(statsCache.data, { headers: CORS_HEADERS });
    }

    const chainKeys: ChainKey[] = ['base', 'avalanche', 'arbitrum', 'polygon'];

    const [counts, partnerBonds, acctBonds, bonded] = await Promise.all([
      Promise.all(chainKeys.map(k => getAgentCount(k))),
      Promise.all(chainKeys.map(k => getBondCount(k, 'partnership'))),
      Promise.all(chainKeys.map(k => getBondCount(k, 'accountability'))),
      Promise.all(chainKeys.map(k => getBondBalance(k))),
    ]);

    const NATIVE_TOKEN: Record<string, string> = {
      base: 'ETH',
      avalanche: 'AVAX',
      arbitrum: 'ETH',
      polygon: 'POL',
    };

    const chainCounts: Record<string, number> = {};
    const chainBonded: Record<string, { amount: number; token: string }> = {};
    let totalIdentities = 0;
    let totalBonds = 0;

    for (let i = 0; i < chainKeys.length; i++) {
      const k = chainKeys[i];
      chainCounts[k] = counts[i];
      chainBonded[k] = { amount: bonded[i], token: NATIVE_TOKEN[k] };
      totalIdentities += counts[i];
      totalBonds += partnerBonds[i] + acctBonds[i];
    }

    const data = {
      totalIdentities,
      activeBonds: totalBonds,
      chainCounts,
      chainBonded,
      timestamp: Date.now(),
    };

    statsCache = { data, ts: Date.now() };
    return NextResponse.json(data, { headers: CORS_HEADERS });
  } catch (e) {
    return NextResponse.json(
      { error: 'Internal server error' },
      { status: 500, headers: CORS_HEADERS },
    );
  }
}
