import { NextRequest, NextResponse } from 'next/server';
import { checkRateLimit, RATE_LIMIT_WRITE } from '../../../../lib/rate-limit';
import {
  checkIdentityRegistered,
  getPartnershipBonds,
  getAccountabilityBonds,
  getReputationData,
  checkValidation,
} from '../../../../lib/onchain-reader';
import type { SupportedChain } from '../../../../lib/contracts';

/**
 * POST /api/agent/status/batch
 *
 * Batch trust profile lookup — check multiple agent addresses in one call.
 * Agents managing sub-agents, dashboards, or orchestrators shouldn't have
 * to make 50 individual status calls.
 *
 * Body: { addresses: ["0x...", "0x..."], chain?: "base" }
 * Max 25 addresses per request.
 */

const MAX_BATCH = 25;
const VALID_CHAINS: SupportedChain[] = ['base', 'avalanche', 'arbitrum', 'polygon'];

function calculateStreetCred(profile: {
  registered: boolean;
  hasBond: boolean;
  bondActive: boolean;
  bondCount: number;
  bondAmountEth: number;
}): number {
  let score = 0;
  if (profile.registered) score += 30;
  if (profile.hasBond) score += 25;
  if (profile.bondActive) score += 15;

  // Bond tier bonus
  if (profile.bondAmountEth >= 0.5) score += 20;
  else if (profile.bondAmountEth >= 0.1) score += 15;
  else if (profile.bondAmountEth >= 0.05) score += 10;
  else if (profile.bondAmountEth >= 0.01) score += 5;

  // Multiple bonds bonus
  if (profile.bondCount > 1) score += 5;

  return Math.min(score, 95);
}

async function getProfileForAddress(address: string, chain: SupportedChain) {
  const [registered, partnerships, accountability, reputation, validation] =
    await Promise.all([
      checkIdentityRegistered(chain, address),
      getPartnershipBonds(chain, address),
      getAccountabilityBonds(chain, address),
      getReputationData(chain, address),
      checkValidation(chain, address),
    ]);

  const bondAmountEth = Number(partnerships.totalStake) / 1e18;
  const streetCred = calculateStreetCred({
    registered,
    hasBond: partnerships.hasBond,
    bondActive: partnerships.activeBonds > 0,
    bondCount: partnerships.bondCount,
    bondAmountEth,
  });

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

  return {
    address,
    chain,
    registered,
    streetCred: { score: streetCred, tier },
    bonds: {
      partnership: { count: partnerships.bondCount, active: partnerships.activeBonds, stakeEth: bondAmountEth },
      accountability: { count: accountability.bondCount, active: accountability.activeBonds },
    },
    reputation: { score: reputation.score, totalEntries: reputation.totalEntries },
    validation: { isValidated: validation.isValidated, validatorCount: validation.validatorCount },
  };
}

// VF-N06: Ethereum address regex — must be 0x followed by exactly 40 hex chars
const ETH_ADDRESS_REGEX = /^0x[a-fA-F0-9]{40}$/;

export async function POST(req: NextRequest) {
  // VF-N01: Rate limiting — use WRITE tier (20 req/min) because each request
  // triggers N parallel RPC calls (RPC amplification risk).
  const rateLimitResponse = checkRateLimit(req, RATE_LIMIT_WRITE);
  if (rateLimitResponse) return rateLimitResponse;

  try {
    const body = await req.json();
    const { addresses, chain: rawChain } = body;

    if (!addresses || !Array.isArray(addresses) || addresses.length === 0) {
      return NextResponse.json(
        { error: 'addresses array is required (max 25)' },
        { status: 400 },
      );
    }

    if (addresses.length > MAX_BATCH) {
      return NextResponse.json(
        { error: `Maximum ${MAX_BATCH} addresses per batch request. Got ${addresses.length}.` },
        { status: 400 },
      );
    }

    // VF-N06: Strict Ethereum address validation — requires full 40-hex-char checksum format
    const invalidAddrs = addresses.filter(
      (a: unknown) => typeof a !== 'string' || !ETH_ADDRESS_REGEX.test(String(a)),
    );
    if (invalidAddrs.length > 0) {
      return NextResponse.json(
        { error: `Invalid Ethereum addresses: ${invalidAddrs.slice(0, 3).join(', ')}${invalidAddrs.length > 3 ? '...' : ''}. Expected 0x followed by 40 hex characters.` },
        { status: 400 },
      );
    }

    const chain: SupportedChain = VALID_CHAINS.includes(rawChain as SupportedChain)
      ? (rawChain as SupportedChain)
      : 'base';

    const start = Date.now();
    const profiles = await Promise.all(
      addresses.map((addr: string) => getProfileForAddress(addr, chain)),
    );
    const latencyMs = Date.now() - start;

    return NextResponse.json({
      chain,
      count: profiles.length,
      latencyMs,
      profiles,
      timestamp: new Date().toISOString(),
    });
  } catch {
    return NextResponse.json({ error: 'Invalid JSON body' }, { status: 400 });
  }
}
