import { useMemo, useEffect, useState, useCallback, useRef } from 'react';
import {
  ReactFlow, Handle, Position, applyNodeChanges,
  type Node, type Edge, type NodeProps, type NodeChange, type ReactFlowInstance,
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';
import {
  Globe, Wifi, Lock, Shield, ShieldAlert, Router,
  AlertCircle, Loader2, Plus, RotateCw,
} from 'lucide-react';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui';
import { TopologyNode, type NodeStatus } from './TopologyNode';
import type { RegisteredDomain } from '@/services/api/networking';
import type { CertEntry } from '@/services/api/cert';

// ── Types ──────────────────────────────────────────────────────────────

type GatewayMode = 'dns-only' | 'l4' | 'l7';

interface DaemonStatuses {
  haproxy?: boolean;
  nftables?: boolean;
  crowdsec?: boolean;
  wireguard?: boolean;
}

interface DdnsRecordInfo {
  ok: boolean;
  ip?: string;
  error?: string;
}

export interface DomainTopologyProps {
  domain: RegisteredDomain;
  cert: CertEntry | undefined;
  ddnsRecord: DdnsRecordInfo | undefined;
  vpnPeerCount: number;
  vpnRunning: boolean;
  vpnConfigured: boolean;
  daemons: DaemonStatuses;
  isManaged: boolean;
  onTogglePublic: () => void;
  onChangeMode: (mode: GatewayMode) => void;
  onChangeBackend?: (address: string) => void;
  onProvisionCert: (domain: string) => void;
  onRenewCert: () => void;
  isProvisioningCert: boolean;
  isRenewingCert: boolean;
  isMutating: boolean;
}

// ── Custom React Flow node ─────────────────────────────────────────────
// Callbacks are passed through data to avoid context issues with React Flow.

const handleStyle = { opacity: 0, width: 4, height: 4 };

function BackendNode({ data, leftHandle, rightHandle, bottomHandle }: {
  data: Record<string, unknown>;
  leftHandle: React.ReactNode;
  rightHandle: React.ReactNode;
  bottomHandle: React.ReactNode;
}) {
  const onChangeBackend = data.onChangeBackend as ((addr: string) => void) | undefined;
  const hasRoutes = data.hasRoutes as boolean;
  const editable = !!onChangeBackend && !hasRoutes;

  const [editing, setEditing] = useState(false);
  const inputRef = useRef<HTMLInputElement>(null);

  const handleSave = () => {
    const val = inputRef.current?.value.trim();
    if (val && onChangeBackend) onChangeBackend(val);
    setEditing(false);
  };

  return (
    <>
      {leftHandle}
      <TopologyNode
        label={editing ? '' : (data.label as string)}
        sublabel={editing ? undefined : (data.sublabel as string | undefined)}
        status="ok"
        className="font-mono"
        interactive={editable && !editing}
        onClick={editable && !editing ? () => setEditing(true) : undefined}
        tooltip={editable && !editing ? 'Click to edit backend address' : undefined}
      >
        {editing && (
          <div className="nopan nodrag" style={{ pointerEvents: 'all' }} onPointerDown={e => e.stopPropagation()}>
            <Input
              ref={inputRef}
              defaultValue={data.label as string}
              className="h-5 text-[10px] font-mono px-1.5"
              autoFocus
              onKeyDown={e => {
                if (e.key === 'Enter') handleSave();
                if (e.key === 'Escape') setEditing(false);
              }}
            />
            <div className="flex gap-1 mt-1">
              <Button variant="ghost" size="sm" className="h-4 text-[9px] px-1 flex-1 !cursor-pointer"
                style={{ pointerEvents: 'all' }} onPointerDown={e => e.stopPropagation()} onClick={handleSave}>
                Save
              </Button>
              <Button variant="ghost" size="sm" className="h-4 text-[9px] px-1 flex-1 !cursor-pointer"
                style={{ pointerEvents: 'all' }} onPointerDown={e => e.stopPropagation()} onClick={() => setEditing(false)}>
                Cancel
              </Button>
            </div>
          </div>
        )}
      </TopologyNode>
      {rightHandle}
      {bottomHandle}
    </>
  );
}

function FlowNode({ data }: NodeProps) {
  const v = data.variant as string;

  const leftHandle = <Handle id="left" type="target" position={Position.Left} style={handleStyle} />;
  const rightHandle = <Handle id="right" type="source" position={Position.Right} style={handleStyle} />;
  const bottomHandle = <Handle id="bottom" type="target" position={Position.Bottom} style={handleStyle} />;

  if (v === 'internet') {
    const isPublic = data.isPublic as boolean;
    const status = data.status as NodeStatus;
    const sublabel = data.sublabel as string;
    const ddnsIp = data.ddnsIp as string | undefined;
    const ddnsError = data.ddnsError as string | undefined;
    const onTogglePublic = data.onTogglePublic as (() => void) | undefined;

    return (
      <>
        {leftHandle}
        <TopologyNode
          label="Internet"
          sublabel={sublabel}
          status={status}
          icon={<Globe className="h-3.5 w-3.5" />}
          interactive
          onClick={onTogglePublic}
          tooltip={
            isPublic ? (
              <div className="space-y-1">
                <div className="font-medium">Public domain</div>
                {ddnsIp && <div>IP: {ddnsIp}</div>}
                {ddnsError && <div className="text-red-400">{ddnsError}</div>}
                <div className="text-muted-foreground">Click to make private</div>
              </div>
            ) : 'Click to make public (enables DDNS)'
          }
        />
        {rightHandle}
      </>
    );
  }

  if (v === 'security') {
    const fwOk = data.firewallOk as boolean;
    const csOk = data.crowdsecOk as boolean;
    const isL4 = data.isL4 as boolean;

    return (
      <>
        {leftHandle}
        <div className="flex flex-col gap-1">
          <TopologyNode
            label="Firewall"
            status={fwOk ? 'ok' : 'na'}
            icon={<Shield className="h-3 w-3" />}
          />
          <TopologyNode
            label="CrowdSec"
            sublabel={isL4 ? 'IP only' : 'HTTP + IP'}
            status={csOk ? 'ok' : 'na'}
            icon={<ShieldAlert className="h-3 w-3" />}
          />
        </div>
        {rightHandle}
      </>
    );
  }

  if (v === 'gateway') {
    const mode = data.mode as GatewayMode;
    const haproxyOk = data.haproxyOk as boolean;
    const isMutating = data.isMutating as boolean;
    const onChangeMode = data.onChangeMode as ((m: GatewayMode) => void) | undefined;

    return (
      <>
        {leftHandle}
        <TopologyNode
          label={mode === 'dns-only' ? 'No gateway' : mode === 'l4' ? 'L4 Passthrough' : 'L7 Proxy'}
          sublabel={mode === 'dns-only' ? 'Traffic goes direct' : mode === 'l4' ? 'SNI routing' : 'HTTP reverse proxy'}
          status={mode === 'dns-only' ? 'inactive' : haproxyOk ? 'ok' : 'error'}
        >
          {onChangeMode && (
            <div className="flex gap-0.5 mt-2 bg-muted rounded p-0.5">
              {(['dns-only', 'l4', 'l7'] as const).map(m => (
                <button key={m} type="button"
                  className={cn(
                    'nopan nodrag flex-1 text-[10px] py-0.5 px-2 rounded transition-colors !cursor-pointer',
                    mode === m ? 'bg-background shadow-sm font-medium' : 'text-muted-foreground hover:text-foreground',
                  )}
                  style={{ pointerEvents: 'all' }}
                  onPointerDown={(e) => e.stopPropagation()}
                  onClick={() => onChangeMode(m)}
                  disabled={isMutating}
                >
                  {m === 'dns-only' ? 'None' : m.toUpperCase()}
                </button>
              ))}
            </div>
          )}
        </TopologyNode>
        {rightHandle}
        {bottomHandle}
      </>
    );
  }

  if (v === 'tls') {
    const status = data.status as NodeStatus;
    const certDomain = data.certDomain as string | undefined;
    const daysLeft = data.daysLeft as number;
    const hasCert = data.hasCert as boolean;
    const provisionDomain = data.provisionDomain as string;
    const expiry = data.expiry as string | undefined;
    const issuer = data.issuer as string | undefined;
    const isProvisioningCert = data.isProvisioningCert as boolean;
    const isRenewingCert = data.isRenewingCert as boolean;
    const onProvisionCert = data.onProvisionCert as ((d: string) => void) | undefined;
    const onRenewCert = data.onRenewCert as (() => void) | undefined;

    return (
      <>
        {leftHandle}
        <TopologyNode
          label="TLS"
          sublabel={certDomain ?? 'No certificate'}
          status={status}
          tooltip={
            hasCert ? (
              <div className="space-y-1">
                <div>Certificate: {certDomain}</div>
                <div>Expires: {expiry ?? 'unknown'} ({daysLeft}d)</div>
                {issuer && <div>Issuer: {issuer}</div>}
              </div>
            ) : 'No TLS certificate provisioned'
          }
        >
          {!hasCert && onProvisionCert && (
            <Button variant="outline" size="sm"
              className="mt-1.5 h-5 text-[10px] gap-0.5 w-full !cursor-pointer"
              style={{ pointerEvents: 'all' }}
              disabled={isProvisioningCert}
              onPointerDown={(e) => e.stopPropagation()}
              onClick={() => onProvisionCert(provisionDomain)}
            >
              {isProvisioningCert ? <Loader2 className="h-2.5 w-2.5 animate-spin" /> : <Plus className="h-2.5 w-2.5" />}
              Provision
            </Button>
          )}
          {hasCert && daysLeft < 30 && onRenewCert && (
            <Button variant="outline" size="sm"
              className="mt-1.5 h-5 text-[10px] gap-0.5 w-full !cursor-pointer"
              style={{ pointerEvents: 'all' }}
              disabled={isRenewingCert}
              onPointerDown={(e) => e.stopPropagation()}
              onClick={() => onRenewCert()}
            >
              {isRenewingCert ? <Loader2 className="h-2.5 w-2.5 animate-spin" /> : <RotateCw className="h-2.5 w-2.5" />}
              Renew
            </Button>
          )}
        </TopologyNode>
        {rightHandle}
      </>
    );
  }

  if (v === 'backend') {
    return <BackendNode data={data} leftHandle={leftHandle} rightHandle={rightHandle} bottomHandle={bottomHandle} />;
  }

  if (v === 'lan') {
    return (
      <>
        {leftHandle}
        <TopologyNode
          label="LAN"
          sublabel="Always connected"
          status="ok"
          icon={<Wifi className="h-3.5 w-3.5" />}
        />
        {rightHandle}
      </>
    );
  }

  if (v === 'vpn') {
    const peerCount = data.peerCount as number;
    const running = data.running as boolean;
    return (
      <>
        {leftHandle}
        <TopologyNode
          label="VPN"
          sublabel={running ? `${peerCount} peer${peerCount !== 1 ? 's' : ''}` : 'Not running'}
          status={running ? 'ok' : 'na'}
          icon={<Lock className="h-3.5 w-3.5" />}
        />
        {rightHandle}
      </>
    );
  }

  if (v === 'router') {
    const ports = data.ports as string;
    return (
      <>
        {leftHandle}
        <TopologyNode
          label="Router"
          sublabel={ports}
          status="na"
          icon={<Router className="h-3 w-3" />}
          tooltip="Your LAN router port-forwards these ports to Wild Central"
        />
        {rightHandle}
      </>
    );
  }

  return null;
}

const nodeTypes = { topology: FlowNode };

// ── Helpers ────────────────────────────────────────────────────────────

function getGatewayMode(domain: RegisteredDomain): GatewayMode {
  const bt = domain.routes?.length ? domain.routes[0].backend.type : domain.backend.type;
  if (bt === 'dns-only') return 'dns-only';
  if (bt === 'tcp-passthrough') return 'l4';
  return 'l7';
}

// ── Main component ─────────────────────────────────────────────────────

/** Align pipeline nodes so their vertical centers match → straight horizontal edges */
const PIPELINE_IDS = new Set(['internet', 'router', 'security', 'gateway', 'tls', 'backend']);

function alignPipelineNodes(nodes: Node[]): Node[] {
  const pipelineNodes = nodes
    .filter(n => PIPELINE_IDS.has(n.id) && (n.measured?.width ?? 0) > 0)
    .sort((a, b) => a.position.x - b.position.x);
  if (pipelineNodes.length < 2) return nodes;

  // Vertical: center-align all pipeline nodes
  let maxHeight = 0;
  for (const n of pipelineNodes) {
    const h = n.measured?.height ?? 0;
    if (h > maxHeight) maxHeight = h;
  }
  const centerY = maxHeight / 2;

  // Horizontal: equalize gaps between nodes
  const totalNodeWidth = pipelineNodes.reduce((sum, n) => sum + (n.measured?.width ?? 0), 0);
  const firstX = pipelineNodes[0].position.x;
  const lastNode = pipelineNodes[pipelineNodes.length - 1];
  const totalSpan = (lastNode.position.x + (lastNode.measured?.width ?? 0)) - firstX;
  const gap = (totalSpan - totalNodeWidth) / (pipelineNodes.length - 1) * 0.75;

  // Build new x positions
  const xPositions = new Map<string, number>();
  let x = firstX;
  for (const n of pipelineNodes) {
    xPositions.set(n.id, x);
    x += (n.measured?.width ?? 0) + gap;
  }

  return nodes.map(n => {
    if (!PIPELINE_IDS.has(n.id)) return n;
    const h = n.measured?.height ?? 0;
    if (h === 0) return n;
    const targetY = centerY - h / 2;
    const targetX = xPositions.get(n.id) ?? n.position.x;
    return { ...n, position: { x: targetX, y: targetY } };
  });
}

function AlignedFlow({ nodes: inputNodes, edges, containerHeight }: { nodes: Node[]; edges: Edge[]; containerHeight: number }) {
  const [nodes, setNodes] = useState(inputNodes);
  const rfRef = useRef<ReactFlowInstance | null>(null);

  // Reset nodes when inputs change (draft updated, card expanded, etc.)
  useEffect(() => { setNodes(inputNodes); }, [inputNodes]);

  // Handle React Flow's internal changes (including dimension measurements)
  const onNodesChange = useCallback((changes: NodeChange[]) => {
    setNodes(prev => {
      const updated = applyNodeChanges(changes, prev);
      if (changes.some(c => c.type === 'dimensions')) {
        const aligned = alignPipelineNodes(updated);
        requestAnimationFrame(() => rfRef.current?.fitView({ padding: 0.15 }));
        return aligned;
      }
      return updated;
    });
  }, []);

  return (
    <div style={{ height: containerHeight }} className="w-full">
      <ReactFlow
        nodes={nodes}
        edges={edges}
        onNodesChange={onNodesChange}
        onInit={instance => { rfRef.current = instance; }}
        nodeTypes={nodeTypes}
        fitView
        fitViewOptions={{ padding: 0.15 }}
        nodesDraggable={false}
        nodesConnectable={false}
        elementsSelectable={false}
        panOnDrag={false}
        zoomOnScroll={false}
        zoomOnPinch={false}
        zoomOnDoubleClick={false}
        preventScrolling={false}
        proOptions={{ hideAttribution: true }}
        className="!bg-transparent"
        style={{ '--xy-edge-label-background-color': 'hsl(var(--card))', '--xy-edge-label-color': 'hsl(var(--muted-foreground))' } as React.CSSProperties}
      />
    </div>
  );
}

export function DomainTopology(props: DomainTopologyProps) {
  const {
    domain, cert, ddnsRecord, vpnPeerCount, vpnRunning, vpnConfigured,
    daemons,
    onTogglePublic, onChangeMode, onChangeBackend, onProvisionCert, onRenewCert,
    isProvisioningCert, isRenewingCert, isMutating,
  } = props;

  const mode = getGatewayMode(domain);
  const isPublic = domain.public;
  const isDnsOnly = mode === 'dns-only';
  const isL4 = mode === 'l4';
  const isL7 = mode === 'l7';
  const showRouter = isPublic;
  const showSecurity = isPublic && !isDnsOnly;
  const showGateway = true; // Always show so mode selector is accessible
  const showTls = isL7;
  const showVpn = vpnConfigured;

  // DDNS
  const ddnsStatus: NodeStatus = !isPublic ? 'inactive' : ddnsRecord?.ok ? 'ok' : ddnsRecord ? 'error' : 'na';
  const ddnsSublabel = !isPublic ? 'Disconnected' : ddnsRecord?.ok ? (ddnsRecord.ip ?? 'Synced') : ddnsRecord?.error ? 'Sync failed' : 'DDNS';

  // TLS
  const hasCert = !!cert?.cert.exists;
  const tlsStatus: NodeStatus = hasCert ? 'ok' : 'error';
  const isWildcardCert = !!(cert?.cert.wildcard || cert?.coveredBy);
  const certDomain = hasCert ? (isWildcardCert ? `*.${cert!.domain}` : cert!.domain) : undefined;
  const daysLeft = cert?.cert.daysLeft ?? 0;
  const provisionDomain = domain.subdomains ? `*.${domain.domain}` : domain.domain;

  // Backend
  const backendLabel = domain.routes?.length ? `${domain.routes.length} backends` : domain.backend.address;
  const backendSublabel = isDnsOnly ? 'Direct access' : isL4 ? 'Handles own TLS' : domain.routes?.length ? 'Path-based routing' : undefined;

  // ── Build nodes & edges ──

  const { nodes, edges } = useMemo(() => {
    const n: Node[] = [];
    const e: Edge[] = [];

    // Column x positions
    let x = 0;
    const sourceX = x;

    x += 170;
    const routerX = showRouter ? x : -1;
    if (showRouter) x += 155;

    const securityX = showSecurity ? x : -1;
    if (showSecurity) x += 165;

    const gatewayX = showGateway ? x : -1;
    if (showGateway) x += 175;

    const tlsX = showTls ? x : -1;
    if (showTls) x += 160;

    const backendX = x;

    // Row y positions — all pipeline nodes start at y=0,
    // then useAlignPipelineNodes() adjusts them after measurement
    const pipelineY = 0;
    const lanY = 120;

    // ── Nodes (callbacks passed via data) ──

    n.push({
      id: 'internet', type: 'topology',
      position: { x: sourceX, y: pipelineY },
      data: {
        variant: 'internet', isPublic, status: ddnsStatus, sublabel: ddnsSublabel,
        ddnsIp: ddnsRecord?.ip, ddnsError: ddnsRecord?.error,
        onTogglePublic,
      },
    });

    if (showRouter) {
      // Show which ports the router forwards — standard HTTPS + HTTP, plus VPN if configured
      const ports = [':443', ':80'];
      if (vpnConfigured) ports.push(`:${51820}`);
      n.push({
        id: 'router', type: 'topology',
        position: { x: routerX, y: pipelineY },
        data: { variant: 'router', ports: `fwd ${ports.join(', ')}` },
      });
    }

    if (showSecurity) {
      n.push({
        id: 'security', type: 'topology',
        position: { x: securityX, y: pipelineY },
        data: { variant: 'security', firewallOk: !!daemons.nftables, crowdsecOk: !!daemons.crowdsec, isL4 },
      });
    }

    if (showGateway) {
      n.push({
        id: 'gateway', type: 'topology',
        position: { x: gatewayX, y: pipelineY },
        data: { variant: 'gateway', mode, haproxyOk: !!daemons.haproxy, isMutating, onChangeMode },
      });
    }

    if (showTls) {
      n.push({
        id: 'tls', type: 'topology',
        position: { x: tlsX, y: pipelineY },
        data: {
          variant: 'tls', status: tlsStatus, certDomain, isWildcardCert, daysLeft, hasCert, provisionDomain,
          expiry: cert?.cert.expiry ? new Date(cert.cert.expiry).toLocaleDateString() : undefined,
          issuer: cert?.cert.issuerCN,
          isProvisioningCert, isRenewingCert, onProvisionCert, onRenewCert,
        },
      });
    }

    n.push({
      id: 'backend', type: 'topology',
      position: { x: backendX, y: pipelineY },
      data: { variant: 'backend', label: backendLabel, sublabel: backendSublabel, onChangeBackend, hasRoutes: !!domain.routes?.length },
    });

    const lanX = showVpn ? sourceX + 120 : sourceX;

    n.push({
      id: 'lan', type: 'topology',
      position: { x: lanX, y: lanY },
      data: { variant: 'lan' },
    });

    if (showVpn) {
      n.push({
        id: 'vpn', type: 'topology',
        position: { x: sourceX, y: lanY },
        data: { variant: 'vpn', peerCount: vpnPeerCount, running: vpnRunning },
      });
    }

    // ── Edges ──

    const pipeline = { type: 'smoothstep' as const, sourceHandle: 'right', targetHandle: 'left', style: { strokeWidth: 1.5 } };
    const labelStyle = { fontSize: 9, fill: 'var(--color-muted-foreground)' };

    // Internet path: Internet → Router → Security → Gateway (or shorter variants)
    if (isPublic) {
      e.push({ id: 'e-internet-router', source: 'internet', target: 'router', ...pipeline });

      if (showSecurity) {
        e.push({ id: 'e-router-security', source: 'router', target: 'security', ...pipeline });
        e.push({ id: 'e-security-gateway', source: 'security', target: 'gateway', ...pipeline });
      } else if (!isDnsOnly) {
        e.push({ id: 'e-router-gateway', source: 'router', target: 'gateway', ...pipeline });
      } else {
        // Direct: router forwards to backend, Central not in path
        e.push({ id: 'e-router-backend', source: 'router', target: 'backend', ...pipeline, style: { ...pipeline.style, strokeDasharray: '6 3' }, label: 'direct', labelStyle });
      }
    }

    // Central processing → backend (not for DNS-only)
    if (!isDnsOnly) {
      if (isL7 && showTls) {
        e.push({ id: 'e-gateway-tls', source: 'gateway', target: 'tls', ...pipeline });
        e.push({ id: 'e-tls-backend', source: 'tls', target: 'backend', ...pipeline, animated: hasCert });
      } else {
        e.push({ id: 'e-gateway-backend', source: 'gateway', target: 'backend', ...pipeline, style: { ...pipeline.style, strokeWidth: isL4 ? 2.5 : 1.5 } });
      }
    }

    // LAN path — enters gateway/backend from below
    const lanTarget = isL7 ? 'gateway' : 'backend';
    e.push({ id: 'e-lan-target', source: 'lan', target: lanTarget, type: 'smoothstep', sourceHandle: 'right', targetHandle: 'bottom', style: { strokeWidth: 1.5 }, label: 'dnsmasq', labelStyle });

    // VPN feeds into LAN (tunnel peers land on the local network)
    if (showVpn) {
      e.push({ id: 'e-vpn-lan', source: 'vpn', target: 'lan', type: 'smoothstep', sourceHandle: 'right', targetHandle: 'left', style: { strokeWidth: 1.5 } });
    }

    return { nodes: n, edges: e };
  }, [
    isPublic, isDnsOnly, isL4, isL7, showRouter, showSecurity, showGateway, showTls, showVpn, vpnConfigured,
    mode, daemons, ddnsStatus, ddnsSublabel, ddnsRecord,
    tlsStatus, certDomain, daysLeft, hasCert, provisionDomain, cert,
    backendLabel, backendSublabel, vpnPeerCount, vpnRunning,
    isMutating, isProvisioningCert, isRenewingCert,
    onTogglePublic, onChangeMode, onChangeBackend, onProvisionCert, onRenewCert, domain.routes,
  ]);

  const containerHeight = 200;

  return (
    <div className="space-y-2 py-2">
      <AlignedFlow nodes={nodes} edges={edges} containerHeight={containerHeight} />

      {/* Warnings */}
      {isDnsOnly && (
        <div className="flex items-center gap-2 text-[10px] text-amber-600 dark:text-amber-400 bg-amber-50/50 dark:bg-amber-950/20 rounded-md px-3 py-1.5">
          <AlertCircle className="h-3 w-3 shrink-0" />
          No firewall, proxy, or TLS protection from Central — traffic goes directly to your server
        </div>
      )}
      {isL7 && !hasCert && (
        <div className="flex items-center gap-2 text-[10px] text-red-600 dark:text-red-400 bg-red-50/50 dark:bg-red-950/20 rounded-md px-3 py-1.5">
          <AlertCircle className="h-3 w-3 shrink-0" />
          L7 routing is inactive until a TLS certificate is provisioned
        </div>
      )}
      {isPublic && ddnsRecord && !ddnsRecord.ok && (
        <div className="flex items-center gap-2 text-[10px] text-red-600 dark:text-red-400 bg-red-50/50 dark:bg-red-950/20 rounded-md px-3 py-1.5">
          <AlertCircle className="h-3 w-3 shrink-0" />
          DDNS sync failed{ddnsRecord.error ? `: ${ddnsRecord.error}` : ''}
        </div>
      )}

      {/* Route table */}
      {isL7 && domain.routes && domain.routes.length > 0 && (
        <div className="bg-muted/30 rounded-md p-2 space-y-1">
          <div className="text-[10px] text-muted-foreground font-medium mb-1">Route table</div>
          {domain.routes.map((route, i) => (
            <div key={i} className="flex items-center gap-3 text-[10px]">
              <span className="font-mono text-muted-foreground w-20 truncate">
                {route.paths?.length ? route.paths.join(', ') : '/*'}
              </span>
              <span className="text-muted-foreground">{'->'}</span>
              <span className="font-mono">{route.backend.address}</span>
              {route.ipAllow && route.ipAllow.length > 0 && (
                <span className="text-muted-foreground flex items-center gap-0.5">
                  <Shield className="h-2.5 w-2.5" />
                  {route.ipAllow.length} IP rules
                </span>
              )}
            </div>
          ))}
        </div>
      )}
    </div>
  );
}
