// ============================================================================
// H33 Agent SDK — Attested MCP Server Example
// ============================================================================
//
// Shows how to wrap MCP tool handlers with automatic H33 attestation.
// Every tool call is cryptographically attested with zero changes to
// your existing handler logic.
//
// Run:  npx tsx examples/mcp-server.ts
// Env:  H33_API_KEY=your-key-here
//

import {
  H33AgentClient,
  H33Session,
  attestedTool,
  toolName,
} from '@h33/agent';

// ── Simulated MCP tool handlers ────────────────────────────────────────────

interface SearchInput {
  query: string;
  limit: number;
}

interface SearchResult {
  id: string;
  title: string;
  score: number;
}

/** Original tool handler -- no H33 code here */
async function searchDatabase(input: SearchInput): Promise<SearchResult[]> {
  // Your existing tool logic, untouched
  return [
    { id: 'claim-001', title: 'Auto claim - fender bender', score: 0.95 },
    { id: 'claim-042', title: 'Property damage - storm', score: 0.87 },
  ];
}

/** Another tool handler */
async function classifyDocument(input: { content: string }): Promise<{ label: string; confidence: number }> {
  return { label: 'medical_record', confidence: 0.92 };
}

// ── Attested MCP Server ────────────────────────────────────────────────────

async function main() {
  const h33 = new H33AgentClient({ apiKey: process.env.H33_API_KEY });

  // Register and start session
  const agent = await h33.register({
    display_name: 'MCP Tool Server',
    canonical_name: 'h33.agent.acme.mcp.server.001',
    agent_type: 'tool_only',
    capabilities: ['use_tools'],
    tenant_id: 'acme-corp',
  });

  const sessionReceipt = await h33.startSession({
    agent_id: agent.agent_id,
    duration_secs: 86400, // 24 hours for a long-running server
    allowed_tools: [
      toolName('acme', 'search', 'v1'),
      toolName('acme', 'classify', 'v1'),
    ],
  });
  const session = new H33Session(h33, sessionReceipt);

  // ── Wrap your handlers ─────────────────────────────────────────────────
  // This is the key integration point. One line per tool.

  const attestedSearch = attestedTool(
    session,
    toolName('acme', 'search', 'v1'),
    searchDatabase,
  );

  const attestedClassify = attestedTool(
    session,
    toolName('acme', 'classify', 'v1'),
    classifyDocument,
  );

  // ── Use them like normal ───────────────────────────────────────────────
  // The wrapped function returns { result, receipt }

  const searchResult = await attestedSearch({ query: 'open claims Q1', limit: 10 });
  console.log('Search results:', searchResult.result);
  console.log('Search receipt:', searchResult.receipt.node_id);
  console.log('Verify:', searchResult.receipt.verification_url);

  const classifyResult = await attestedClassify({ content: 'Patient presented with...' });
  console.log('Classification:', classifyResult.result);
  console.log('Classify receipt:', classifyResult.receipt.node_id);
  console.log('Verify:', classifyResult.receipt.verification_url);

  // ── Error handling ─────────────────────────────────────────────────────
  // If a tool throws, the failure is attested before re-throwing

  const riskyTool = attestedTool(
    session,
    toolName('acme', 'risky', 'v1'),
    async (_input: unknown) => {
      throw new Error('Connection refused');
    },
  );

  try {
    await riskyTool({ target: 'unreachable-host' });
  } catch (err) {
    console.log('Tool failure attested and re-thrown:', (err as Error).message);
  }

  console.log(`\nTotal attested tool calls: ${session.actions}`);
  await session.end();
}

main().catch(console.error);
