import { useState } from 'react';
import { supabase } from '@/integrations/supabase/client';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { AdminLayout } from '@/components/admin/AdminLayout';
import { AdminPageHeader } from '@/components/admin/AdminPageHeader';
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Badge } from '@/components/ui/badge';
import { Skeleton } from '@/components/ui/skeleton';
import { Switch } from '@/components/ui/switch';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from '@/components/ui/dialog';
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogTrigger,
} from '@/components/ui/alert-dialog';
import { Globe, Plus, Copy, Check, ArrowDownLeft, ArrowUpRight, AlertCircle, Pencil, Zap, Loader2, Search, Shield, Cpu, Trash2, Send } from 'lucide-react';
import { A2ATestChat } from '@/components/admin/federation/A2ATestChat';
import { A2AActivityLog } from '@/components/admin/federation/A2AActivityLog';
import { AgentInvites } from '@/components/admin/federation/AgentInvites';
import { McpActivityLog } from '@/components/admin/federation/McpActivityLog';
import { McpFindings } from '@/components/admin/federation/McpFindings';
import { PeerChannelsInline } from '@/components/admin/federation/PeerChannelsInline';
import { MissionDispatchDialog } from '@/components/admin/federation/MissionDispatchDialog';
import { useFederationConnections } from '@/hooks/useFederationConnections';
import { useToast } from '@/hooks/use-toast';
import { useA2APeers, useCreateA2APeer, useUpdateA2APeer, useDeleteA2APeer, useA2AActivity } from '@/hooks/useA2A';
import { useQueryClient } from '@tanstack/react-query';
import { formatDistanceToNow } from 'date-fns';
import { InvitationTree } from '@/components/admin/federation/InvitationTree';

export default function FederationPage() {
  const { toast } = useToast();
  const { data: peers, isLoading: peersLoading } = useA2APeers();
  const { data: activity, isLoading: activityLoading } = useA2AActivity();
  const createPeer = useCreateA2APeer();
  const updatePeer = useUpdateA2APeer();
  const deletePeer = useDeleteA2APeer();
  
  const queryClient = useQueryClient();

  const [dialogOpen, setDialogOpen] = useState(false);
  const [newPeerName, setNewPeerName] = useState('');
  const [newPeerUrl, setNewPeerUrl] = useState('');
  const [newPeerOutboundToken, setNewPeerOutboundToken] = useState('');
  const [newPeerInboundToken, setNewPeerInboundToken] = useState('');
  const [newPeerGatewayToken, setNewPeerGatewayToken] = useState('');
  const [showToken, setShowToken] = useState<string | null>(null);
  const [copiedToken, setCopiedToken] = useState(false);

  // Edit-peer state removed — channel-level edits live in PeerChannelsInline

  const [generatedInboundToken, setGeneratedInboundToken] = useState<string | null>(null);
   const [testingPeerId, setTestingPeerId] = useState<string | null>(null);
  const [testResult, setTestResult] = useState<{ peerId: string; success: boolean; message: string } | null>(null);

  const [discoveringPeerId, setDiscoveringPeerId] = useState<string | null>(null);
  const [auditingPeerId, setAuditingPeerId] = useState<string | null>(null);
  const [auditResult, setAuditResult] = useState<{ peerId: string; success: boolean; text: string } | null>(null);

  // Auto-discover state for Add Peer dialog
  const [probeLoading, setProbeLoading] = useState(false);
  const [probeResult, setProbeResult] = useState<{ success: boolean; agent_card?: any; found_at?: string; error?: string } | null>(null);
  const [probeTimeoutRef, setProbeTimeoutRef] = useState<ReturnType<typeof setTimeout> | null>(null);

  // Auto-probe when URL changes (debounced)
  const handleUrlChange = (url: string) => {
    setNewPeerUrl(url);
    setProbeResult(null);

    if (probeTimeoutRef) clearTimeout(probeTimeoutRef);

    // Strip known agent card paths so users can paste the full URL
    const knownPaths = [
      '/.well-known/agent-card.json', '/.well-known/agent.json',
      '/agent-card.json', '/agent-card',
      '/a2a/agent-card', '/functions/v1/agent-card',
    ];
    let trimmed = url.trim().replace(/\/$/, '');
    for (const p of knownPaths) {
      if (trimmed.endsWith(p)) {
        trimmed = trimmed.slice(0, -p.length);
        break;
      }
    }
    if (!trimmed || !trimmed.startsWith('http')) return;

    const timeoutId = setTimeout(async () => {
      setProbeLoading(true);
      try {
        const { data: { session } } = await supabase.auth.getSession();
        if (!session) return;

        const res = await fetch(
          `${import.meta.env.VITE_SUPABASE_URL}/functions/v1/a2a/discover`,
          {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
              'Authorization': `Bearer ${session.access_token}`,
              'apikey': import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY,
            },
            body: JSON.stringify({ action: 'probe', peer_url: trimmed }),
          }
        );
        const data = await res.json();
        setProbeResult(data);

        // Auto-fill name from discovered card
        if (data.success && data.agent_card?.name && !newPeerName) {
          setNewPeerName(data.agent_card.name);
        }
      } catch {
        setProbeResult({ success: false, error: 'Probe request failed' });
      } finally {
        setProbeLoading(false);
      }
    }, 800);
    setProbeTimeoutRef(timeoutId);
  };

  const handleTestConnection = async (peer: { id: string; name: string; url: string; capabilities?: unknown }) => {
    if (!peer.url) {
      toast({ title: 'No URL', description: 'This peer has no outbound URL configured.', variant: 'destructive' });
      return;
    }
    setTestingPeerId(peer.id);
    setTestResult(null);
    try {
      const { supabase } = await import('@/integrations/supabase/client');
      const { data: { session } } = await supabase.auth.getSession();
      if (!session) throw new Error('Not authenticated');

      const caps = (peer.capabilities && typeof peer.capabilities === 'object' && !Array.isArray(peer.capabilities))
        ? peer.capabilities as Record<string, unknown>
        : {};
      const skills = Array.isArray(caps.skills) ? caps.skills as Array<Record<string, unknown>> : [];
      const skillIds = skills
        .map((skill) => typeof skill.id === 'string' ? skill.id : null)
        .filter((id): id is string => Boolean(id));

      const preferredSkill = skillIds.includes('healthcheck')
        ? 'healthcheck'
        : skillIds[0] ?? null;

      const requestBody = preferredSkill
        ? { peer_name: peer.name, skill: preferredSkill, arguments: {} }
        : { peer_name: peer.name, message: 'ping' };

      const res = await fetch(
        `${import.meta.env.VITE_SUPABASE_URL}/functions/v1/a2a/outbound`,
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${session.access_token}`,
            'apikey': import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY,
          },
          body: JSON.stringify(requestBody),
        }
      );
      const data = await res.json();
      const errorMsg = data.error
        ? (typeof data.error === 'object' ? (data.error.message || JSON.stringify(data.error)) : String(data.error))
        : null;
      if (res.ok && !errorMsg) {
        const successLabel = preferredSkill ? `Skill \"${preferredSkill}\" responded.` : 'Peer responded successfully.';
        setTestResult({ peerId: peer.id, success: true, message: `Connected! Response: ${JSON.stringify(data).slice(0, 120)}` });
        toast({ title: 'Connection OK', description: `${peer.name}: ${successLabel}` });
      } else {
        const displayError = errorMsg || `HTTP ${res.status}`;
        setTestResult({ peerId: peer.id, success: false, message: displayError });
        toast({ title: 'Connection failed', description: displayError, variant: 'destructive' });
      }
    } catch (err: unknown) {
      const msg = err instanceof Error ? err.message : 'Unknown error';
      setTestResult({ peerId: peer.id, success: false, message: msg });
      toast({ title: 'Connection error', description: msg, variant: 'destructive' });
    } finally {
      setTestingPeerId(null);
    }
  };

  const handleDiscover = async (peer: { id: string; name: string; url: string; capabilities?: unknown }) => {
    if (!peer.url) return;
    setDiscoveringPeerId(peer.id);
    try {
      // Use edge function to discover (avoids CORS issues with direct browser fetch)
      const { data, error } = await supabase.functions.invoke('a2a/discover', {
        body: { peer_id: peer.id, action: 'discover' },
      });

      if (error) throw error;
      if (data?.error) throw new Error(data.error);

      const card = data?.agent_card;
      toast({
        title: 'Skills discovered',
        description: `Found ${card?.skills?.length || 0} skills from ${card?.name || peer.name}`,
      });
      queryClient.invalidateQueries({ queryKey: ['a2a-peers'] });
    } catch (err: unknown) {
      const msg = err instanceof Error ? err.message : 'Unknown error';
      toast({ title: 'Discovery failed', description: msg, variant: 'destructive' });
    } finally {
      setDiscoveringPeerId(null);
    }
  };

  const handleRunAudit = async (peer: { id: string; name: string; url: string }) => {
    if (!peer.url) return;
    setAuditingPeerId(peer.id);
    setAuditResult(null);
    try {
      const { supabase } = await import('@/integrations/supabase/client');
      const { data: { session } } = await supabase.auth.getSession();
      if (!session) throw new Error('Not authenticated');

      toast({ title: 'Audit started', description: `Asking ${peer.name} to audit your site...` });

      const res = await fetch(
        `${import.meta.env.VITE_SUPABASE_URL}/functions/v1/a2a/discover`,
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${session.access_token}`,
            'apikey': import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY,
          },
          body: JSON.stringify({
            peer_id: peer.id,
            action: 'audit',
            site_url: window.location.origin,
          }),
        }
      );
      const data = await res.json();
      
      // Extract readable text from the result
      let auditText = '';
      const taskResult = data.result?.result;
      if (taskResult?.artifacts?.length) {
        for (const artifact of taskResult.artifacts) {
          for (const part of artifact.parts || []) {
            if (part.kind === 'text' || part.type === 'text') {
              auditText += (part.text || '') + '\n';
            }
          }
        }
      }
      if (!auditText && taskResult?.status?.message?.parts) {
        for (const part of taskResult.status.message.parts) {
          if (part.kind === 'text' || part.type === 'text') {
            auditText += (part.text || '') + '\n';
          }
        }
      }

      if (data.success) {
        setAuditResult({ peerId: peer.id, success: true, text: auditText || 'Audit completed — check objectives for findings.' });
        toast({ title: 'Audit complete', description: 'Findings have been saved as objectives.' });
      } else {
        const errMsg = data.error
          ? (typeof data.error === 'object' ? data.error.message || JSON.stringify(data.error) : String(data.error))
          : 'Audit failed';
        setAuditResult({ peerId: peer.id, success: false, text: errMsg });
        toast({ title: 'Audit failed', description: errMsg, variant: 'destructive' });
      }
    } catch (err: unknown) {
      const msg = err instanceof Error ? err.message : 'Unknown error';
      setAuditResult({ peerId: peer.id, success: false, text: msg });
      toast({ title: 'Audit error', description: msg, variant: 'destructive' });
    } finally {
      setAuditingPeerId(null);
    }
  };

  const handleCreatePeer = async () => {
    if (!newPeerName) return;

    // Auto-generate inbound token if not provided
    let inboundToken = newPeerInboundToken;
    if (!inboundToken) {
      const bytes = new Uint8Array(32);
      crypto.getRandomValues(bytes);
      inboundToken = Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
    }

    const result = await createPeer.mutateAsync({
      name: newPeerName,
      url: newPeerUrl || undefined,
      outbound_token: newPeerOutboundToken || undefined,
      inbound_token: inboundToken,
      gateway_token: newPeerGatewayToken || undefined,
    });

    if (result) {
      // Show the inbound token so user can share it with the peer
      setGeneratedInboundToken(inboundToken);
      if (!newPeerOutboundToken && newPeerUrl) {
        setShowToken(result.outbound_token);
      }
      setDialogOpen(false);
      setNewPeerName('');
      setNewPeerUrl('');
      setNewPeerOutboundToken('');
      setNewPeerInboundToken('');
      setNewPeerGatewayToken('');
    }
  };

  const handleCopyToken = async (token: string) => {
    await navigator.clipboard.writeText(token);
    setCopiedToken(true);
    setTimeout(() => setCopiedToken(false), 2000);
    toast({ title: 'Copied', description: 'Token copied to clipboard' });
  };

  const handleToggleStatus = async (peerId: string, currentStatus: string) => {
    const newStatus = currentStatus === 'active' ? 'paused' : 'active';
    await updatePeer.mutateAsync({ id: peerId, status: newStatus });
  };

  // handleRevoke removed — credential revocation is per-channel (MCP via API Keys, A2A via remove channel)

  // openEditDialog/handleSaveEdit removed — channel-level edits live in PeerChannelsInline

  // --- Protocol detection ---
  // Prefers the explicit `transport` column (set during peer creation or auto-discovery).
  // Falls back to legacy heuristics for older peers that pre-date the column.
  const getPeerTransport = (peer: { transport?: string | null; gateway_token?: string | null; capabilities?: unknown }): 'responses' | 'a2a' | 'mcp_inbound' => {
    if (peer.transport === 'mcp_inbound') return 'mcp_inbound';
    if (peer.transport === 'openresponses') return 'responses';
    if (peer.transport === 'a2a') return 'a2a';
    if (peer.gateway_token) return 'responses';
    const caps = (peer.capabilities && typeof peer.capabilities === 'object') ? peer.capabilities as Record<string, unknown> : {};
    if (caps.protocol === 'responses' || caps.protocol === 'openai') return 'responses';
    return 'a2a';
  };

  const transportLabel = (t: 'responses' | 'a2a' | 'mcp_inbound') => {
    if (t === 'mcp_inbound') return 'MCP Inbound';
    if (t === 'responses') return '/v1/responses';
    return 'A2A';
  };

  const [dispatchDialogPeer, setDispatchDialogPeer] = useState<any>(null);

  const activePeers = peers?.filter(p => p.status !== 'revoked') || [];
  const totalRequests = peers?.reduce((sum, p) => sum + (p.request_count || 0), 0) || 0;

  const statusColor = (status: string) => {
    switch (status) {
      case 'active': return 'default';
      case 'paused': return 'secondary';
      case 'revoked': return 'destructive';
      default: return 'outline';
    }
  };

  return (
    <AdminLayout>
      <div className="space-y-8">
        <AdminPageHeader
          title="Federation"
          description="Connect with external agents — A2A peers (JSON-RPC) or Orchestrator Agents (/v1/responses + MCP)"
        />

        <Tabs defaultValue="a2a-peers" className="space-y-6">
          <TabsList>
            <TabsTrigger value="a2a-peers">Peers & Channels</TabsTrigger>
            <TabsTrigger value="tree">Invitation Tree</TabsTrigger>
            <TabsTrigger value="activity">Activity & Findings</TabsTrigger>
            <TabsTrigger value="agent-invites">Agent Invites</TabsTrigger>
          </TabsList>

          <TabsContent value="a2a-peers" className="space-y-8">
        {/* Summary */}
        <div className="grid gap-4 sm:grid-cols-3">
          <Card>
            <CardContent className="pt-6">
              <div className="flex items-center gap-4">
                <div className="h-12 w-12 rounded-xl bg-primary/10 flex items-center justify-center">
                  <Globe className="h-6 w-6 text-primary" />
                </div>
                <div>
                  <p className="text-2xl font-bold">{activePeers.length}</p>
                  <p className="text-sm text-muted-foreground">connected peers</p>
                </div>
              </div>
            </CardContent>
          </Card>

          <Card>
            <CardContent className="pt-6">
              <div className="flex items-center gap-4">
                <div className="h-12 w-12 rounded-xl bg-muted flex items-center justify-center">
                  <ArrowDownLeft className="h-6 w-6 text-muted-foreground" />
                </div>
                <div>
                  <p className="text-2xl font-bold">{totalRequests}</p>
                  <p className="text-sm text-muted-foreground">total requests</p>
                </div>
              </div>
            </CardContent>
          </Card>

          <Card>
            <CardContent className="pt-6">
              <div className="flex items-center gap-4">
                <div className="h-12 w-12 rounded-xl bg-muted flex items-center justify-center">
                  <ArrowUpRight className="h-6 w-6 text-muted-foreground" />
                </div>
                <div>
                  <p className="text-2xl font-bold">
                    {activity?.filter(a => a.status === 'success').length || 0}
                  </p>
                  <p className="text-sm text-muted-foreground">successful today</p>
                </div>
              </div>
            </CardContent>
          </Card>
        </div>

        {/* Inbound token reveal dialog — post-creation wizard */}
        <Dialog open={!!generatedInboundToken} onOpenChange={() => setGeneratedInboundToken(null)}>
          <DialogContent>
            <DialogHeader>
              <DialogTitle className="flex items-center gap-2">
                <Check className="h-5 w-5 text-green-500" />
                Peer Created — Share These Details
              </DialogTitle>
              <DialogDescription>
                Share these connection details with the peer so they can reach you.
              </DialogDescription>
            </DialogHeader>
            <div className="space-y-4">
              {/* Available Endpoints */}
              <div className="space-y-3">
                <Label className="text-xs font-medium flex items-center gap-1.5">
                  <span className="h-5 w-5 rounded-full bg-primary text-primary-foreground flex items-center justify-center text-[10px] font-bold">1</span>
                  Available Endpoints
                </Label>

                {/* A2A */}
                <div className="space-y-1">
                  <p className="text-[10px] font-medium text-muted-foreground uppercase tracking-wider">A2A (JSON-RPC)</p>
                  <div className="flex items-center gap-2 p-2.5 bg-muted rounded-md font-mono text-xs break-all">
                    <span className="flex-1">{import.meta.env.VITE_SUPABASE_URL}/functions/v1/a2a/ingest</span>
                    <Button variant="ghost" size="icon" className="shrink-0 h-7 w-7" onClick={() => handleCopyToken(`${import.meta.env.VITE_SUPABASE_URL}/functions/v1/a2a/ingest`)}>
                      {copiedToken ? <Check className="h-3.5 w-3.5" /> : <Copy className="h-3.5 w-3.5" />}
                    </Button>
                  </div>
                </div>

                {/* MCP REST */}
                <div className="space-y-1">
                  <p className="text-[10px] font-medium text-muted-foreground uppercase tracking-wider">MCP / REST</p>
                  <div className="flex items-center gap-2 p-2.5 bg-muted rounded-md font-mono text-xs break-all">
                    <span className="flex-1">{import.meta.env.VITE_SUPABASE_URL}/functions/v1/mcp-server/rest</span>
                    <Button variant="ghost" size="icon" className="shrink-0 h-7 w-7" onClick={() => handleCopyToken(`${import.meta.env.VITE_SUPABASE_URL}/functions/v1/mcp-server/rest`)}>
                      {copiedToken ? <Check className="h-3.5 w-3.5" /> : <Copy className="h-3.5 w-3.5" />}
                    </Button>
                  </div>
                </div>
              </div>

              {/* Bearer Token */}
              <div className="space-y-2">
                <Label className="text-xs font-medium flex items-center gap-1.5">
                  <span className="h-5 w-5 rounded-full bg-primary text-primary-foreground flex items-center justify-center text-[10px] font-bold">2</span>
                  Bearer Token <span className="text-destructive text-[10px]">(shown once)</span>
                </Label>
                <div className="flex items-center gap-2 p-3 bg-muted rounded-md font-mono text-xs break-all">
                  <span className="flex-1">{generatedInboundToken}</span>
                  <Button variant="ghost" size="icon" className="shrink-0" onClick={() => generatedInboundToken && handleCopyToken(generatedInboundToken)}>
                    {copiedToken ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}
                  </Button>
                </div>
              </div>

              <div className="rounded-lg border border-border/50 p-3 bg-muted/30 text-xs text-muted-foreground space-y-1">
                <p className="font-medium text-foreground">The peer should use:</p>
                <code className="block bg-background rounded px-2 py-1.5 text-[11px]">
                  Authorization: Bearer &lt;token&gt;
                </code>
                <p className="text-[10px] mt-1">Same token works for all endpoints above.</p>
              </div>
            </div>
            <DialogFooter>
              <Button onClick={() => setGeneratedInboundToken(null)}>Done</Button>
            </DialogFooter>
          </DialogContent>
        </Dialog>

        {/* Outbound token reveal dialog */}
        <Dialog open={!!showToken} onOpenChange={() => setShowToken(null)}>
          <DialogContent>
            <DialogHeader>
              <DialogTitle>Outbound Token Generated</DialogTitle>
              <DialogDescription>
                This token is used when your instance calls the peer's API.
              </DialogDescription>
            </DialogHeader>
            <div className="flex items-center gap-2 p-3 bg-muted rounded-md font-mono text-sm break-all">
              <span className="flex-1">{showToken}</span>
              <Button
                variant="ghost"
                size="icon"
                onClick={() => showToken && handleCopyToken(showToken)}
              >
                {copiedToken ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}
              </Button>
            </div>
            <DialogFooter>
              <Button onClick={() => setShowToken(null)}>Done</Button>
            </DialogFooter>
          </DialogContent>
        </Dialog>
        {/* Edit Peer dialog removed — credentials/URL now managed per Channel (see PeerChannelsInline) */}

        {/* Add Peer */}
        <div className="flex justify-end">
          <Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
            <DialogTrigger asChild>
              <Button>
                <Plus className="h-4 w-4 mr-2" />
                Connect Peer
              </Button>
            </DialogTrigger>
            <DialogContent className="sm:max-w-lg">
              <DialogHeader>
                <DialogTitle>Connect New Peer</DialogTitle>
                <DialogDescription>
                  Register an external agent peer. We'll auto-detect their capabilities via A2A, MCP, or REST.
                </DialogDescription>
              </DialogHeader>
              <div className="space-y-5">
                {/* Step 1: URL */}
                <div className="space-y-2">
                  <div className="flex items-center gap-2">
                    <div className="h-6 w-6 rounded-full bg-primary text-primary-foreground flex items-center justify-center text-xs font-bold">1</div>
                    <Label className="font-medium">Peer URL</Label>
                  </div>
                  <div className="relative">
                    <Input
                      placeholder="https://peer.example.com"
                      value={newPeerUrl}
                      onChange={e => handleUrlChange(e.target.value)}
                    />
                    {probeLoading && (
                      <Loader2 className="h-4 w-4 animate-spin absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground" />
                    )}
                  </div>
                  <p className="text-xs text-muted-foreground">
                    Leave empty for inbound-only peers that only call your endpoint.
                  </p>
                  {/* Probe result */}
                  {probeResult && (
                    <div className={`rounded-lg border p-3 text-sm ${probeResult.success ? 'border-green-500/30 bg-green-500/5' : 'border-yellow-500/30 bg-yellow-500/5'}`}>
                      {probeResult.success ? (
                        <div className="space-y-2">
                          <div className="flex items-center gap-2 text-green-700 dark:text-green-400">
                            <Check className="h-4 w-4" />
                            <span className="font-medium">Agent found: {probeResult.agent_card?.name}</span>
                          </div>
                          {probeResult.agent_card?.description && (
                            <p className="text-xs text-muted-foreground">{probeResult.agent_card.description}</p>
                          )}
                          {probeResult.agent_card?.skills?.length > 0 && (
                            <div className="flex flex-wrap gap-1">
                              {probeResult.agent_card.skills.slice(0, 8).map((s: any) => (
                                <Badge key={s.id} variant="secondary" className="text-[10px]">
                                  {s.name || s.id}
                                </Badge>
                              ))}
                              {probeResult.agent_card.skills.length > 8 && (
                                <Badge variant="outline" className="text-[10px]">
                                  +{probeResult.agent_card.skills.length - 8} more
                                </Badge>
                              )}
                            </div>
                          )}
                          {probeResult.found_at && (
                            <p className="text-[10px] text-muted-foreground font-mono">Card at: {probeResult.found_at}</p>
                          )}
                        </div>
                      ) : (
                        <div className="flex items-center gap-2 text-yellow-700 dark:text-yellow-400">
                          <AlertCircle className="h-4 w-4" />
                          <span>No agent card found — you can still add manually</span>
                        </div>
                      )}
                    </div>
                  )}
                </div>

                {/* Step 2: Name */}
                <div className="space-y-2">
                  <div className="flex items-center gap-2">
                    <div className="h-6 w-6 rounded-full bg-primary text-primary-foreground flex items-center justify-center text-xs font-bold">2</div>
                    <Label className="font-medium">Peer Name</Label>
                  </div>
                  <Input
                    placeholder="e.g. OpenClaw"
                    value={newPeerName}
                    onChange={e => setNewPeerName(e.target.value)}
                  />
                </div>

                {/* Step 3: Tokens */}
                <div className="space-y-3">
                  <div className="flex items-center gap-2">
                    <div className="h-6 w-6 rounded-full bg-primary text-primary-foreground flex items-center justify-center text-xs font-bold">3</div>
                    <Label className="font-medium">Authentication</Label>
                  </div>

                  <div className="rounded-lg border border-border/50 p-3 space-y-3 bg-muted/30">
                    <div className="space-y-1.5">
                      <Label className="text-xs flex items-center gap-1.5">
                        <ArrowDownLeft className="h-3 w-3 text-blue-500" />
                        Inbound Token <span className="text-muted-foreground">(they → you)</span>
                      </Label>
                      <Input
                        placeholder="Auto-generated if empty"
                        value={newPeerInboundToken}
                        onChange={e => setNewPeerInboundToken(e.target.value)}
                        className="text-xs"
                      />
                      <p className="text-[10px] text-muted-foreground">
                        You'll share this token with the peer after creation.
                      </p>
                    </div>

                    {newPeerUrl && (
                      <>
                        <div className="space-y-1.5">
                          <Label className="text-xs flex items-center gap-1.5">
                            <ArrowUpRight className="h-3 w-3 text-green-500" />
                            Outbound Token <span className="text-muted-foreground">(you → them)</span>
                          </Label>
                          <Input
                            placeholder="Paste the token they gave you"
                            value={newPeerOutboundToken}
                            onChange={e => setNewPeerOutboundToken(e.target.value)}
                            className="text-xs"
                          />
                          <p className="text-[10px] text-muted-foreground">
                            The API key or token the peer gave you for calling their endpoint.
                          </p>
                        </div>

                        <div className="space-y-1.5">
                          <Label className="text-xs flex items-center gap-1.5">
                            <ArrowUpRight className="h-3 w-3 text-purple-500" />
                            Gateway Token <span className="text-muted-foreground">(optional — /v1/responses)</span>
                          </Label>
                          <Input
                            placeholder="Separate token for responses-style API"
                            value={newPeerGatewayToken}
                            onChange={e => setNewPeerGatewayToken(e.target.value)}
                            className="text-xs"
                          />
                          <p className="text-[10px] text-muted-foreground">
                            Only needed if the peer requires a separate key for /v1/responses calls.
                          </p>
                        </div>
                      </>
                    )}
                  </div>
                </div>
              </div>
              <DialogFooter>
                <Button variant="outline" onClick={() => { setDialogOpen(false); setProbeResult(null); }}>Cancel</Button>
                <Button onClick={handleCreatePeer} disabled={!newPeerName || createPeer.isPending}>
                  {createPeer.isPending ? 'Creating...' : 'Create Peer'}
                </Button>
              </DialogFooter>
            </DialogContent>
          </Dialog>
        </div>

        {/* Peers List */}
        {peersLoading ? (
          <div className="space-y-4">
            {[1, 2].map(i => <Skeleton key={i} className="h-32" />)}
          </div>
        ) : peers?.length === 0 ? (
          <Card>
            <CardContent className="py-12 text-center">
              <Globe className="h-12 w-12 text-muted-foreground/30 mx-auto mb-4" />
              <p className="text-muted-foreground">No peers connected yet</p>
              <p className="text-sm text-muted-foreground/60 mt-1">
                Connect your first A2A peer to start federating
              </p>
            </CardContent>
          </Card>
        ) : (
          <div className="space-y-4">
            {peers?.map(peer => (
              <Card key={peer.id} className={peer.status === 'revoked' ? 'opacity-50' : ''}>
                <CardHeader className="pb-3">
                  <div className="flex items-center justify-between">
                    <div className="flex items-center gap-3">
                      <div className="h-10 w-10 rounded-lg bg-primary/10 flex items-center justify-center">
                        <Globe className="h-5 w-5 text-primary" />
                      </div>
                      <div>
                        <CardTitle className="text-base">
                          {((peer.capabilities as any)?.agent_name) || peer.name}
                        </CardTitle>
                        {peer.url ? (
                          <CardDescription className="font-mono text-xs">{peer.url}</CardDescription>
                        ) : getPeerTransport(peer) === 'mcp_inbound' ? (
                          <CardDescription className="text-xs flex items-center gap-1.5">
                            <ArrowDownLeft className="h-3 w-3" />
                            Auto-discovered via MCP authentication
                          </CardDescription>
                        ) : null}
                        {(peer.capabilities as any)?.agent_description && (
                          <p className="text-xs text-muted-foreground mt-0.5">
                            {(peer.capabilities as any).agent_description}
                          </p>
                        )}
                      </div>
                    </div>
                    <div className="flex items-center gap-2">
                      <Badge
                        variant={getPeerTransport(peer) === 'mcp_inbound' ? 'secondary' : 'outline'}
                        className="text-[10px]"
                      >
                        {transportLabel(getPeerTransport(peer))}
                      </Badge>
                      {(peer.capabilities as any)?.protocol_version && (
                        <Badge variant="outline" className="text-[10px]">
                          v{(peer.capabilities as any).protocol_version}
                        </Badge>
                      )}
                      <Badge variant={statusColor(peer.status)}>{peer.status}</Badge>
                    </div>
                  </div>
                </CardHeader>
                <CardContent className="space-y-3">
                  <PeerChannelsInline peerId={peer.id} peerName={peer.name} />

                  {(() => {
                    const skills = (peer.capabilities as any)?.skills;
                    if (!skills?.length) return null;
                    return (
                      <div className="flex flex-wrap gap-1.5">
                        {skills.map((skill: any) => (
                          <Badge key={skill.id} variant="secondary" className="text-[11px] font-normal gap-1">
                            <Cpu className="h-3 w-3" />
                            {skill.name || skill.id}
                          </Badge>
                        ))}
                      </div>
                    );
                  })()}

                  <div className="flex items-center justify-between">
                    <div className="flex items-center gap-6 text-sm text-muted-foreground">
                      <span>{peer.request_count} requests</span>
                      {peer.last_seen_at && (
                        <span>Last seen {formatDistanceToNow(new Date(peer.last_seen_at), { addSuffix: true })}</span>
                      )}
                      {(peer.capabilities as any)?.discovered_at && (
                        <span className="text-xs">Skills discovered {formatDistanceToNow(new Date((peer.capabilities as any).discovered_at), { addSuffix: true })}</span>
                      )}
                    </div>
                    <div className="flex items-center gap-2">
                      {peer.status !== 'revoked' ? (
                         <>
                          {peer.url && getPeerTransport(peer) === 'a2a' && (
                            <>
                              <Button
                                variant="outline"
                                size="sm"
                                onClick={() => handleDiscover(peer)}
                                disabled={discoveringPeerId === peer.id}
                              >
                                {discoveringPeerId === peer.id ? (
                                  <Loader2 className="h-3 w-3 mr-1 animate-spin" />
                                ) : (
                                  <Search className="h-3 w-3 mr-1" />
                                )}
                                Discover
                              </Button>
                              {(peer.capabilities as any)?.skills?.some((s: any) => s.id === 'openclaw_audit') && (
                                <Button
                                  variant="outline"
                                  size="sm"
                                  onClick={() => handleRunAudit(peer)}
                                  disabled={auditingPeerId === peer.id}
                                  className="border-primary/30 text-primary hover:bg-primary/5"
                                >
                                  {auditingPeerId === peer.id ? (
                                    <Loader2 className="h-3 w-3 mr-1 animate-spin" />
                                  ) : (
                                    <Shield className="h-3 w-3 mr-1" />
                                  )}
                                  Audit
                                </Button>
                              )}
                              <A2ATestChat peer={{ id: peer.id, name: peer.name, url: peer.url, status: peer.status }} />
                              <Button
                                variant="outline"
                                size="sm"
                                onClick={() => handleTestConnection(peer)}
                                disabled={testingPeerId === peer.id}
                              >
                                {testingPeerId === peer.id ? (
                                  <Loader2 className="h-3 w-3 mr-1 animate-spin" />
                                ) : (
                                  <Zap className="h-3 w-3 mr-1" />
                                )}
                                Test
                              </Button>
                            </>
                          )}
                          {peer.url && getPeerTransport(peer) === 'responses' && (
                            <Button
                              variant="outline"
                              size="sm"
                              onClick={() => setDispatchDialogPeer(peer)}
                            >
                              <Send className="h-3 w-3 mr-1" />
                              Dispatch Mission
                            </Button>
                          )}
                          {/* Edit / token-copy buttons removed — credentials now live per Channel */}
                          <Switch
                            checked={peer.status === 'active'}
                            onCheckedChange={() => handleToggleStatus(peer.id, peer.status)}
                          />
                          {/* Peer-level Revoke removed — credential revoke lives per channel:
                              MCP keys → /admin/api-keys, A2A tokens → remove the channel itself */}
                          <AlertDialog>
                            <AlertDialogTrigger asChild>
                              <Button variant="ghost" size="icon" className="h-8 w-8 text-destructive hover:text-destructive">
                                <Trash2 className="h-3.5 w-3.5" />
                              </Button>
                            </AlertDialogTrigger>
                            <AlertDialogContent>
                              <AlertDialogHeader>
                                <AlertDialogTitle>Delete peer permanently?</AlertDialogTitle>
                                <AlertDialogDescription>
                                  This will permanently remove {peer.name} and all associated activity records. This cannot be undone.
                                </AlertDialogDescription>
                              </AlertDialogHeader>
                              <AlertDialogFooter>
                                <AlertDialogCancel>Cancel</AlertDialogCancel>
                                <AlertDialogAction
                                  onClick={() => deletePeer.mutate(peer.id)}
                                  className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
                                >
                                  Delete
                                </AlertDialogAction>
                              </AlertDialogFooter>
                            </AlertDialogContent>
                          </AlertDialog>
                        </>
                      ) : (
                        <AlertDialog>
                          <AlertDialogTrigger asChild>
                            <Button variant="ghost" size="icon" className="h-8 w-8 text-destructive hover:text-destructive">
                              <Trash2 className="h-3.5 w-3.5" />
                            </Button>
                          </AlertDialogTrigger>
                          <AlertDialogContent>
                            <AlertDialogHeader>
                              <AlertDialogTitle>Delete peer permanently?</AlertDialogTitle>
                              <AlertDialogDescription>
                                This will permanently remove {peer.name}. This cannot be undone.
                              </AlertDialogDescription>
                            </AlertDialogHeader>
                            <AlertDialogFooter>
                              <AlertDialogCancel>Cancel</AlertDialogCancel>
                              <AlertDialogAction
                                onClick={() => deletePeer.mutate(peer.id)}
                                className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
                              >
                                Delete
                              </AlertDialogAction>
                            </AlertDialogFooter>
                          </AlertDialogContent>
                        </AlertDialog>
                      )}
                    </div>
                  </div>
                  {testResult && testResult.peerId === peer.id && (
                    <div className={`p-2 rounded text-xs font-mono ${
                      testResult.success 
                        ? 'bg-green-500/10 text-green-600 border border-green-500/20' 
                        : 'bg-destructive/10 text-destructive border border-destructive/20'
                    }`}>
                      {testResult.message}
                    </div>
                  )}
                  {auditResult && auditResult.peerId === peer.id && (
                    <div className={`p-3 rounded text-xs ${
                      auditResult.success 
                        ? 'bg-green-500/10 text-foreground border border-green-500/20' 
                        : 'bg-destructive/10 text-destructive border border-destructive/20'
                    }`}>
                      <p className="font-medium mb-1">{auditResult.success ? '✓ Audit Complete' : '✗ Audit Failed'}</p>
                      <pre className="whitespace-pre-wrap text-[11px] text-muted-foreground max-h-60 overflow-auto">
                        {auditResult.text}
                      </pre>
                    </div>
                  )}
                </CardContent>
              </Card>
            ))}
          </div>
        )}

        {/* Activity Log */}
        <div>
          <h2 className="text-sm font-medium text-muted-foreground uppercase tracking-wider mb-4">
            Communication Log
          </h2>
          <A2AActivityLog />
        </div>

        {/* Dispatch Mission Dialog (structured envelope) */}
        <MissionDispatchDialog
          peer={dispatchDialogPeer ? { id: dispatchDialogPeer.id, name: dispatchDialogPeer.name } : null}
          onClose={() => setDispatchDialogPeer(null)}
        />
          </TabsContent>

          <TabsContent value="activity" className="space-y-8">
            <div>
              <h2 className="text-sm font-medium text-muted-foreground uppercase tracking-wider mb-4">
                Agent Findings
              </h2>
              <McpFindings />
            </div>
            <div>
              <h2 className="text-sm font-medium text-muted-foreground uppercase tracking-wider mb-4">
                MCP Activity Log
              </h2>
              <McpActivityLog />
            </div>
          </TabsContent>

          <TabsContent value="tree">
            <InvitationTree />
          </TabsContent>

          <TabsContent value="agent-invites">
            <AgentInvites />
          </TabsContent>
        </Tabs>
      </div>
    </AdminLayout>
  );
}
