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

/**
 * GET /api/agent/credentials
 *
 * Query credential data from the VaultfireCapabilityCredentials contract.
 *
 * Query params:
 *   ?address=0x...      — (required) agent address to look up
 *   ?capability=0x...   — (optional) hex-encoded capability hash to check for an active credential
 *   ?chain=base         — chain to query (default: "base")
 *
 * Returns:
 *   Agent profile: totalCredentials, activeCredentials, totalTaskProofs.
 *   If `capability` is provided, also returns hasActiveCredential (bool).
 */

const CONTRACTS: Record<string, string> = {
  base:      '0x4C7fddDdae8855283e98dA80BDf7aEa51A0b772B',
  avalanche: '0x6750D28865434344e04e1D0a6044394b726C3dfE',
  arbitrum:  '0x472dF1dD6D8218D0BF748e910E32861dAb88EDA6',
  polygon:   '0x1762e484A48558Ea5Cd056ac2CDf43FBbA52ba58',
};

const ABI = [
  {
    name: 'getAgentProfile',
    type: 'function',
    stateMutability: 'view',
    inputs: [{ name: 'agent', type: 'address' }],
    outputs: [
      { name: 'totalCredentials',  type: 'uint256' },
      { name: 'activeCredentials', type: 'uint256' },
      { name: 'totalTaskProofs',   type: 'uint256' },
    ],
  },
  {
    name: 'hasActiveCredential',
    type: 'function',
    stateMutability: 'view',
    inputs: [
      { name: 'agent',      type: 'address' },
      { name: 'capability', type: 'bytes32' },
    ],
    outputs: [{ name: '', type: 'bool' }],
  },
];

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

    if (!address) {
      return NextResponse.json({ error: 'Missing required query param: address' }, { status: 400 });
    }

    if (!ethers.isAddress(address)) {
      return NextResponse.json({ error: 'Invalid wallet address' }, { 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 contractAddress = CONTRACTS[chain];

    const profile = await withFailover(chain, async (provider) => {
      const contract = new ethers.Contract(contractAddress, ABI, provider);
      return contract.getAgentProfile(address);
    });

    const response: Record<string, unknown> = {
      address,
      chain,
      contract: contractAddress,
      agentProfile: {
        totalCredentials:  profile.totalCredentials.toString(),
        activeCredentials: profile.activeCredentials.toString(),
        totalTaskProofs:   profile.totalTaskProofs.toString(),
      },
    };

    if (capability) {
      // Pad/normalise the capability hash to bytes32
      let capBytes32: string;
      try {
        // If it's already a 32-byte hex string (with or without 0x), use it directly
        const raw = capability.startsWith('0x') ? capability : `0x${capability}`;
        capBytes32 = ethers.zeroPadValue(raw, 32);
      } catch {
        return NextResponse.json({ error: 'Invalid capability hash — expected a hex bytes32 value' }, { status: 400 });
      }

      const hasCredential: boolean = await withFailover(chain, async (provider) => {
        const contract = new ethers.Contract(contractAddress, ABI, provider);
        return contract.hasActiveCredential(address, capBytes32);
      });
      response.capability = capability;
      response.hasActiveCredential = hasCredential;
    }

    return NextResponse.json(response);
  } catch (error: any) {
    console.error('[credentials] Internal error:', error instanceof Error ? error.message : error);
    return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
  }
}
