import { NextRequest, NextResponse } from 'next/server';
import { ethers } from 'ethers';
import { resolveChain, SUPPORTED_CHAINS } from '../../_lib/resolve-chain';
import { RPC_FALLBACKS } from '../../_lib/rpc-retry';

/**
 * GET /api/agent/bridge
 *
 * Query real bridge state from VaultfireTeleporterBridge contracts.
 *
 * Query params:
 *   ?chain=base          — chain to query (default: "base")
 *   ?address=0x...       — (optional) check if a specific agent is recognized
 *
 * Returns: synced counts, bridge status, and optional agent recognition check.
 */

const CONTRACTS: Record<string, string> = {
  base:      '0x62edf0cBc8Fa3d98B6A07197DFE9cb1c128a7eC7',
  avalanche: '0x1762e484A48558Ea5Cd056ac2CDf43FBbA52ba58',
  arbitrum:  '0x7b9293B05Bd0fcb7458d06A364078761B8E8848e',
  polygon:   '0x7b9293B05Bd0fcb7458d06A364078761B8E8848e',
};

const RPC: Record<string, string> = {
  base:      'https://mainnet.base.org',
  avalanche: 'https://api.avax.network/ext/bc/C/rpc',
  arbitrum:  'https://arb1.arbitrum.io/rpc',
  polygon:   'https://rpc-mainnet.matic.quiknode.pro',
};

const ABI = [
  { name: 'outboundNonce', type: 'function', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },
  { name: 'paused', type: 'function', stateMutability: 'view', inputs: [], outputs: [{ type: 'bool' }] },
  { name: 'remoteChainId', type: 'function', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },
  { name: 'getSyncedAgentCount', type: 'function', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },
  { name: 'getSyncedPartnershipBondCount', type: 'function', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },
  { name: 'getSyncedAccountabilityBondCount', type: 'function', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },
  { name: 'getSyncedReputationCount', type: 'function', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },
  { name: 'getSyncedValidationCount', type: 'function', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },
  { name: 'isAgentRecognized', type: 'function', stateMutability: 'view', inputs: [{ name: 'agent', type: 'address' }], outputs: [{ type: 'bool' }] },
  { name: 'getRelayerCount', type: 'function', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },
  { name: 'lastProcessedNonce', type: 'function', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },
];

export async function GET(req: NextRequest) {
  try {
    const { searchParams } = new URL(req.url);
    const chain = resolveChain(searchParams.get('chain'));
    const address = searchParams.get('address');

    if (!chain) {
      return NextResponse.json(
        { error: `Unsupported chain. Use one of: ${SUPPORTED_CHAINS.join(', ')} (or chain IDs: 8453, 43114, 42161, 137)` },
        { status: 400 },
      );
    }
    const contractAddress = CONTRACTS[chain];

    // Prefer the canonical fallback list's primary RPC — more reliable than
    // the route-local map. Individual calls below already have per-call .catch().
    const rpcUrl = (RPC_FALLBACKS[chain] && RPC_FALLBACKS[chain][0]) || RPC[chain];
    const provider = new ethers.JsonRpcProvider(rpcUrl);
    const contract = new ethers.Contract(contractAddress, ABI, provider);

    const [
      outboundNonce,
      paused,
      remoteChainId,
      syncedAgents,
      syncedPartnershipBonds,
      syncedAccountabilityBonds,
      syncedReputations,
      syncedValidations,
      relayerCount,
      lastProcessedNonce,
    ] = await Promise.all([
      contract.outboundNonce().catch(() => BigInt(0)),
      contract.paused().catch(() => false),
      contract.remoteChainId().catch(() => BigInt(0)),
      contract.getSyncedAgentCount().catch(() => BigInt(0)),
      contract.getSyncedPartnershipBondCount().catch(() => BigInt(0)),
      contract.getSyncedAccountabilityBondCount().catch(() => BigInt(0)),
      contract.getSyncedReputationCount().catch(() => BigInt(0)),
      contract.getSyncedValidationCount().catch(() => BigInt(0)),
      contract.getRelayerCount().catch(() => BigInt(0)),
      contract.lastProcessedNonce().catch(() => BigInt(0)),
    ]);

    const response: Record<string, unknown> = {
      chain,
      contract: contractAddress,
      bridge: {
        outboundMessages: outboundNonce.toString(),
        inboundProcessed: lastProcessedNonce.toString(),
        paused: paused,
        remoteChainId: remoteChainId.toString(),
        relayerCount: relayerCount.toString(),
      },
      synced: {
        agents: syncedAgents.toString(),
        partnershipBonds: syncedPartnershipBonds.toString(),
        accountabilityBonds: syncedAccountabilityBonds.toString(),
        reputations: syncedReputations.toString(),
        validations: syncedValidations.toString(),
      },
    };

    // Optional: check if a specific agent is recognized
    if (address) {
      if (!ethers.isAddress(address)) {
        return NextResponse.json({ error: 'Invalid address' }, { status: 400 });
      }
      const recognized = await contract.isAgentRecognized(address).catch(() => false);
      response.agentCheck = {
        address,
        recognized,
      };
    }

    return NextResponse.json(response);
  } catch (error: unknown) {
    // VF-N05/VF-14: Never leak raw error messages to clients — log server-side only
    console.error('[bridge] Unhandled error:', error);
    return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
  }
}
