/**
 * Example: Verify an agent's trust before delegating a task via A2A.
 *
 * This pattern shows how to:
 * 1. Fetch another agent's Agent Card from their /.well-known/agent.json
 * 2. Verify their Vaultfire trust claims on-chain
 * 3. Only delegate if they meet your trust threshold
 */

import { verifyAgentCard, discoverTrustedAgents } from '@vaultfire/a2a';
import type { EnrichedAgentCard } from '@vaultfire/a2a';

// ─── Pattern 1: Verify a specific agent before delegating ─────────────────────

async function delegateToAgent(targetAgentUrl: string, task: object) {
  console.log(`Fetching Agent Card from ${targetAgentUrl}...`);

  // 1. Fetch the target agent's card
  const response = await fetch(`${targetAgentUrl}/.well-known/agent.json`);
  const card = (await response.json()) as EnrichedAgentCard;

  // 2. Check if it has Vaultfire trust data
  if (!card['x-vaultfire']) {
    throw new Error('Agent does not have Vaultfire trust extension — refusing to delegate');
  }

  // 3. Verify the trust claims on-chain
  console.log('Verifying trust claims on-chain...');
  const verification = await verifyAgentCard(card);

  console.log(`\n--- Verification Result ---`);
  console.log(`Trusted: ${verification.trusted}`);
  console.log(`Reason: ${verification.reason}`);
  console.log(`Street Cred: ${verification.streetCred.score} (${verification.streetCred.tier})`);
  console.log(`Active Bonds: ${verification.bonds.active}`);

  // 4. Enforce trust threshold: require at least Silver tier (35+ points)
  const MINIMUM_STREET_CRED = 35;
  if (!verification.trusted || verification.streetCred.score < MINIMUM_STREET_CRED) {
    throw new Error(
      `Agent trust verification failed: ${verification.reason} ` +
        `(score: ${verification.streetCred.score}, required: ${MINIMUM_STREET_CRED})`
    );
  }

  // 5. Proceed with delegation
  console.log(`\nTrust verified! Delegating task to ${card.name}...`);

  const delegateResponse = await fetch(`${targetAgentUrl}/tasks`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ task }),
  });

  return delegateResponse.json();
}

// ─── Pattern 2: Discover trusted agents and delegate to the best one ──────────

async function delegateToTrustedPool(task: object) {
  console.log('Discovering trusted agents on Base...');

  const agents = await discoverTrustedAgents({
    chain: 'base',
    minStreetCred: 50, // Gold tier minimum
    requireActive: true,
    limit: 10,
  });

  if (agents.length === 0) {
    throw new Error('No trusted agents found matching criteria');
  }

  console.log(`Found ${agents.length} trusted agents:`);
  for (const agent of agents) {
    console.log(
      `  - ${agent.address} | ${agent.agentType} | Score: ${agent.streetCred.score} (${agent.streetCred.tier})`
    );
  }

  // Pick the highest-rated agent (already sorted by score descending)
  const best = agents[0];
  console.log(`\nDelegating to best agent: ${best.address} (${best.streetCred.tier} tier)`);

  // Fetch their card to get the URL
  if (!best.agentURI) {
    throw new Error('Agent has no URI registered on-chain');
  }

  const response = await fetch(`${best.agentURI}/tasks`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ task }),
  });

  return response.json();
}

// ─── Main ─────────────────────────────────────────────────────────────────────

async function main() {
  console.log('=== Vaultfire A2A Trust Verification Example ===\n');

  // Example 1: Verify before delegating
  console.log('--- Pattern 1: Verify specific agent ---');
  try {
    // In a real scenario, replace with actual agent URL
    await delegateToAgent('https://target-agent.example.com', {
      type: 'data-analysis',
      data: [1, 2, 3, 4, 5],
    });
  } catch (err) {
    console.log(`Expected error (demo agent doesn't exist): ${(err as Error).message}`);
  }

  // Example 2: Discover and delegate
  console.log('\n--- Pattern 2: Discover trusted agents ---');
  try {
    await delegateToPool({ type: 'translation', text: 'Hello world', targetLang: 'es' });
  } catch (err) {
    console.log(`Note: ${(err as Error).message}`);
  }
}

async function delegateToPool(task: object) {
  return delegateToTrustedPool(task);
}

main().catch(console.error);
