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/analytics?address=0x...&chain=base
 *
 * Agent performance analytics — real on-chain data aggregated into
 * a single view of an agent's activity, trust trajectory, and standing.
 *
 * Reads from: IdentityRegistry, PartnershipBonds, AccountabilityBonds,
 * ReputationRegistry, ReputationStaking, TrustOracle, CapabilityCredentials,
 * DisputeResolution, VaultfireTeleporterBridge.
 */

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',
};

// Contract addresses per chain
const CONTRACTS: Record<string, Record<string, string>> = {
  base: {
    identity:       '0xa7BD20bf5De63df949cA5Be2F20835978eCba81A',
    partnership:    '0x01C479F0c039fEC40c0Cf1c5C921bab457d57441',
    accountability: '0x6750D28865434344e04e1D0a6044394b726C3dfE',
    reputation:     '0xdB54B8925664816187646174bdBb6Ac658A55a5F',
    staking:        '0xd42BBfD3061A38D4B5540317A31D90212380069b',
    oracle:         '0xF945aA87dB4E1d14aa7d0572501afa166374B776',
    credentials:    '0x4C7fddDdae8855283e98dA80BDf7aEa51A0b772B',
    disputes:       '0x3a681b6eF98c6d35643Ca631eE50EF35edd6BcBD',
    bridge:         '0x62edf0cBc8Fa3d98B6A07197DFE9cb1c128a7eC7',
  },
  avalanche: {
    identity:       '0x7448057C95Fb8a8B974a566cdcc9Cd042166A3f8',
    partnership:    '0xDC8447c66fE9D9c7D54607A98346A15324b7985D',
    accountability: '0x376831fB2457E34559891c32bEb61c442053C066',
    staking:        '0x32211773C8266774A704aeD471f8eF073f34bA79',
    oracle:         '0x01C479F0c039fEC40c0Cf1c5C921bab457d57441',
    credentials:    '0x6750D28865434344e04e1D0a6044394b726C3dfE',
    disputes:       '0x98afd1440B2238D73c1394720277a6d031fCbbD0',
    bridge:         '0x1762e484A48558Ea5Cd056ac2CDf43FBbA52ba58',
  },
  arbitrum: {
    identity:       '0x83dd216449B3F0574E39043ECFE275946fa492e9',
    partnership:    '0xdB54B8925664816187646174bdBb6Ac658A55a5F',
    accountability: '0xef3A944f4d7bb376699C83A29d7Cb42C90D9B6F0',
    staking:        '0x9d4AbeAa8201e6f1649c296dd179Bbb3c401f96F',
    oracle:         '0xFeF83A66fC1f3c8311070FDd502cd90deD0B3C33',
    credentials:    '0x472dF1dD6D8218D0BF748e910E32861dAb88EDA6',
    disputes:       '0x152a0446958f48EB3F1f5126FAF418D663359e95',
    bridge:         '0x7b9293B05Bd0fcb7458d06A364078761B8E8848e',
  },
  polygon: {
    identity:       '0xD9bF6D92a1D9ee44a48c38481c046a819CBdf2ba',
    partnership:    '0x83dd216449B3F0574E39043ECFE275946fa492e9',
    accountability: '0xdB54B8925664816187646174bdBb6Ac658A55a5F',
    staking:        '0x3ceA2B0853B76Ac75603C1fa2A29D96A4467Bb79',
    oracle:         '0xFa8ed66E27379942cB90BB5f612F0170a5dE4924',
    credentials:    '0x1762e484A48558Ea5Cd056ac2CDf43FBbA52ba58',
    disputes:       '0x5F7680a9a720c03812532A735D1165D9f97c0Cd1',
    bridge:         '0x7b9293B05Bd0fcb7458d06A364078761B8E8848e',
  },
};

// Minimal ABI fragments for reads
const IDENTITY_ABI = [
  { name: 'isRegisteredAgent', type: 'function', stateMutability: 'view', inputs: [{ type: 'address' }], outputs: [{ type: 'bool' }] },
];
const BONDS_ABI = [
  { name: 'getBondsByParticipantCount', type: 'function', stateMutability: 'view', inputs: [{ type: 'address' }], outputs: [{ type: 'uint256' }] },
];
const REPUTATION_ABI = [
  { name: 'getReputationScore', type: 'function', stateMutability: 'view', inputs: [{ type: 'address' }], outputs: [{ type: 'uint256' }] },
];
const STAKING_ABI = [
  { name: 'getTotalStake', type: 'function', stateMutability: 'view', inputs: [{ type: 'address' }], outputs: [{ type: 'uint256' }] },
  { name: 'getVouchCount', type: 'function', stateMutability: 'view', inputs: [{ type: 'address' }], outputs: [{ type: 'uint256' }] },
];
const ORACLE_ABI = [
  { name: 'getAttestationCount', type: 'function', stateMutability: 'view', inputs: [{ type: 'address' }], outputs: [{ type: 'uint256' }] },
];
const CREDENTIALS_ABI = [
  { name: 'getCredentialCount', type: 'function', stateMutability: 'view', inputs: [{ type: 'address' }], outputs: [{ type: 'uint256' }] },
];
const DISPUTES_ABI = [
  { name: 'getDisputeCountByParty', type: 'function', stateMutability: 'view', inputs: [{ type: 'address' }], outputs: [{ type: 'uint256' }] },
];
const BRIDGE_ABI = [
  { name: 'isAgentRecognized', type: 'function', stateMutability: 'view', inputs: [{ type: 'address' }], outputs: [{ type: 'bool' }] },
];

async function safeCall<T>(fn: () => Promise<T>, fallback: T): Promise<T> {
  try { return await fn(); } catch { return fallback; }
}

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

  if (!address || !ethers.isAddress(address)) {
    return NextResponse.json({ error: 'Valid address parameter required (0x...)' }, { status: 400 });
  }

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

  const start = Date.now();

  // Use the canonical fallback RPC list so this route benefits from the same
  // endpoints maintained in app/api/_lib/rpc-retry.ts.
  const rpcUrl = (RPC_FALLBACKS[chain] && RPC_FALLBACKS[chain][0]) || RPC[chain];
  const provider = new ethers.JsonRpcProvider(rpcUrl);

  // Read all on-chain data in parallel. Each call is wrapped in safeCall so a
  // single failing contract read returns 0/false rather than crashing the route.
  const [
    isRegistered,
    partnershipCount,
    accountabilityCount,
    reputationScore,
    totalStake,
    vouchCount,
    attestationCount,
    credentialCount,
    disputeCount,
    bridgeRecognized,
  ] = await Promise.all([
    safeCall(() => new ethers.Contract(addrs.identity, IDENTITY_ABI, provider).isRegisteredAgent(address), false),
    safeCall(() => new ethers.Contract(addrs.partnership, BONDS_ABI, provider).getBondsByParticipantCount(address).then(Number), 0),
    safeCall(() => new ethers.Contract(addrs.accountability, BONDS_ABI, provider).getBondsByParticipantCount(address).then(Number), 0),
    safeCall(() => new ethers.Contract(addrs.reputation || addrs.identity, REPUTATION_ABI, provider).getReputationScore(address).then(Number), 0),
    safeCall(() => new ethers.Contract(addrs.staking, STAKING_ABI, provider).getTotalStake(address).then((v: bigint) => Number(v) / 1e18), 0),
    safeCall(() => new ethers.Contract(addrs.staking, STAKING_ABI, provider).getVouchCount(address).then(Number), 0),
    safeCall(() => new ethers.Contract(addrs.oracle, ORACLE_ABI, provider).getAttestationCount(address).then(Number), 0),
    safeCall(() => new ethers.Contract(addrs.credentials, CREDENTIALS_ABI, provider).getCredentialCount(address).then(Number), 0),
    safeCall(() => new ethers.Contract(addrs.disputes, DISPUTES_ABI, provider).getDisputeCountByParty(address).then(Number), 0),
    safeCall(() => new ethers.Contract(addrs.bridge, BRIDGE_ABI, provider).isAgentRecognized(address), false),
  ]);

  const latencyMs = Date.now() - start;

  // Calculate Street Cred
  let streetCred = 0;
  if (isRegistered) streetCred += 30;
  if (partnershipCount > 0) streetCred += 25;
  if (totalStake > 0) streetCred += 15;
  if (attestationCount > 0) streetCred += 10;
  if (bridgeRecognized) streetCred += 10;
  if (partnershipCount > 1) streetCred += 5;
  streetCred = Math.min(streetCred, 95);

  let tier = 'Newcomer';
  if (streetCred >= 80) tier = 'Diamond';
  else if (streetCred >= 65) tier = 'Platinum';
  else if (streetCred >= 50) tier = 'Gold';
  else if (streetCred >= 35) tier = 'Silver';
  else if (streetCred >= 20) tier = 'Bronze';

  // Activity summary
  const totalActivity = partnershipCount + accountabilityCount + vouchCount + attestationCount + credentialCount;

  return NextResponse.json({
    address,
    chain,
    latencyMs,
    streetCred: { score: streetCred, tier, maxPossible: 95 },
    identity: {
      registered: isRegistered,
      bridgeRecognized,
    },
    bonds: {
      partnership: { count: partnershipCount },
      accountability: { count: accountabilityCount },
      totalBonds: partnershipCount + accountabilityCount,
    },
    reputation: {
      onChainScore: reputationScore,
      maxScore: 10000,
    },
    staking: {
      totalStakeEth: totalStake,
      vouchesReceived: vouchCount,
    },
    oracle: {
      attestationCount,
    },
    credentials: {
      count: credentialCount,
    },
    disputes: {
      involvedCount: disputeCount,
    },
    summary: {
      totalOnChainActivity: totalActivity,
      chainsActive: 1, // This endpoint queries one chain; use /status for multi-chain
      trustLevel: tier,
    },
    timestamp: new Date().toISOString(),
  });
}
