import { useDynamicSectors } from '@/hooks/useDynamicSectors.ts';
import { useTranslation } from '@/hooks/useI18n.tsx';
import { motion } from 'framer-motion';
import { Briefcase, Hammer, Layers, ShoppingBag } from 'lucide-react';
import React, { useMemo, useState } from 'react';

interface ResourceExchangeVisualizationProps {
  maxItems?: number;
  showStats?: boolean;
}

// Layout constants - single source of truth
const LAYOUT_CONFIG = {
  SVG_VIEWBOX_SIZE: 500,
  CENTER_X: 250,
  CENTER_Y: 250,
  SECTOR_RADIUS: 180,
  RESOURCE_ICON_OFFSET: 45, // Distance from sector center for unidirectional
  RESOURCE_ICON_SIZE: 7, // Radius in SVG units
  SECTOR_NODE_RADIUS: 32,
  SECTOR_ICON_BACKGROUND_RADIUS: 22,
  CONNECTION_BADGE_OFFSET: 28,
  CONNECTION_BADGE_RADIUS: 14,
  LABEL_OFFSET_Y: 55,
  NODE_RADIUS_FOR_PARTICLES: 35, // Hide particles within this radius
} as const;

// Layout calculator - handles all coordinate transformations
// Uses SVG's native coordinate system - no pixel conversion needed
class LayoutCalculator {
  private svgSize: number;

  constructor(svgSize: number = LAYOUT_CONFIG.SVG_VIEWBOX_SIZE) {
    this.svgSize = svgSize;
  }

  // Calculate sector positions in circular layout (SVG coordinates)
  calculateSectorPositions(count: number): Array<{ x: number; y: number; angle: number }> {
    if (count === 0) return [];

    const { CENTER_X, CENTER_Y, SECTOR_RADIUS } = LAYOUT_CONFIG;
    const angleStep = (2 * Math.PI) / count;

    return Array.from({ length: count }, (_, index) => {
      const angle = index * angleStep - Math.PI / 2;
      return {
        x: CENTER_X + SECTOR_RADIUS * Math.cos(angle),
        y: CENTER_Y + SECTOR_RADIUS * Math.sin(angle),
        angle,
      };
    });
  }

  // Calculate resource icon position (SVG coordinates)
  // Avoids overlapping with connection count badges
  calculateResourceIconPosition(
    fromPos: { x: number; y: number },
    toPos: { x: number; y: number },
    isBidirectional: boolean,
    fromIndex: number,
    toIndex: number,
    showStats: boolean = false
  ): { x: number; y: number } {
    const angle = Math.atan2(toPos.y - fromPos.y, toPos.x - fromPos.x);

    if (isBidirectional) {
      // Position at midpoint, offset perpendicular
      // Use from/to indices to ensure consistent side assignment
      const midpointX = (fromPos.x + toPos.x) / 2;
      const midpointY = (fromPos.y + toPos.y) / 2;
      const perpAngle = angle + Math.PI / 2;
      // Ensure consistent side: lower index → higher index goes left, reverse goes right
      const sideOffset = fromIndex < toIndex ? -12 : 12;
      return {
        x: midpointX + Math.cos(perpAngle) * sideOffset,
        y: midpointY + Math.sin(perpAngle) * sideOffset,
      };
    } else {
      // Position next to source organization
      let resourceX = fromPos.x + Math.cos(angle) * LAYOUT_CONFIG.RESOURCE_ICON_OFFSET;
      let resourceY = fromPos.y + Math.sin(angle) * LAYOUT_CONFIG.RESOURCE_ICON_OFFSET;

      // Check if resource icon would overlap with badge (badge is at +28x, -28y from sector center)
      if (showStats) {
        const badgeX = fromPos.x + LAYOUT_CONFIG.CONNECTION_BADGE_OFFSET;
        const badgeY = fromPos.y - LAYOUT_CONFIG.CONNECTION_BADGE_OFFSET;
        const badgeRadius = LAYOUT_CONFIG.CONNECTION_BADGE_RADIUS + 8; // Add padding
        const resourceIconRadius = 14; // Half of foreignObject size (28/2)

        const distanceToBadge = Math.sqrt(
          Math.pow(resourceX - badgeX, 2) + Math.pow(resourceY - badgeY, 2)
        );

        // If too close to badge, adjust position
        if (distanceToBadge < badgeRadius + resourceIconRadius) {
          // Move resource icon further along the connection direction
          const adjustedOffset = LAYOUT_CONFIG.RESOURCE_ICON_OFFSET + 20;
          resourceX = fromPos.x + Math.cos(angle) * adjustedOffset;
          resourceY = fromPos.y + Math.sin(angle) * adjustedOffset;

          // Also check if still too close, if so offset perpendicularly
          const newDistanceToBadge = Math.sqrt(
            Math.pow(resourceX - badgeX, 2) + Math.pow(resourceY - badgeY, 2)
          );

          if (newDistanceToBadge < badgeRadius + resourceIconRadius) {
            // Offset perpendicular to avoid badge
            const perpAngle = angle + Math.PI / 2;
            const perpOffset = badgeRadius + resourceIconRadius - newDistanceToBadge + 5;
            // Choose side that's away from badge
            const badgeAngle = Math.atan2(badgeY - fromPos.y, badgeX - fromPos.x);
            const angleDiff = angle - badgeAngle;
            const perpDirection = Math.abs(angleDiff) < Math.PI / 2 ? -1 : 1;
            resourceX += Math.cos(perpAngle) * perpOffset * perpDirection;
            resourceY += Math.sin(perpAngle) * perpOffset * perpDirection;
          }
        }
      }

      return {
        x: resourceX,
        y: resourceY,
      };
    }
  }

  // Calculate connection line start position (SVG coordinates)
  calculateConnectionStart(
    fromPos: { x: number; y: number },
    resourceIconPos: { x: number; y: number },
    isBidirectional: boolean
  ): { x: number; y: number } {
    if (isBidirectional) {
      return { x: fromPos.x, y: fromPos.y };
    } else {
      const angle = Math.atan2(resourceIconPos.y - fromPos.y, resourceIconPos.x - fromPos.x);
      return {
        x: resourceIconPos.x + Math.cos(angle) * LAYOUT_CONFIG.RESOURCE_ICON_SIZE,
        y: resourceIconPos.y + Math.sin(angle) * LAYOUT_CONFIG.RESOURCE_ICON_SIZE,
      };
    }
  }

  // Get SVG coordinate bounds for foreignObject positioning
  // Returns position and size in SVG coordinate system
  getForeignObjectBounds(
    svgX: number,
    svgY: number,
    size: number = 44
  ): {
    x: number;
    y: number;
    width: number;
    height: number;
  } {
    // Center the foreignObject on the SVG coordinate
    return {
      x: svgX - size / 2,
      y: svgY - size / 2,
      width: size,
      height: size,
    };
  }

  // Calculate distance between two points
  distance(p1: { x: number; y: number }, p2: { x: number; y: number }): number {
    return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
  }
}

// Resource types that can flow between sectors
const RESOURCE_TYPES = [
  { type: 'products', icon: ShoppingBag, color: 'text-blue-500' },
  { type: 'services', icon: Briefcase, color: 'text-purple-500' },
  { type: 'materials', icon: Layers, color: 'text-green-500' },
  { type: 'equipment', icon: Hammer, color: 'text-orange-500' },
] as const;

// Generate potential connections between sectors based on common symbiosis patterns
// Creates varying connection counts (1-4 connections per sector) for visual interest
const generateConnections = (sectors: Array<{ backendName?: string; colorKey: string }>) => {
  const connections: Array<{ from: number; to: number; resourceType: string; strength: number }> =
    [];
  // Track resource types used per sector to ensure variety
  const sectorResourceUsage: Map<number, Set<number>> = new Map();

  if (sectors.length < 2) return connections;

  // Connection pattern per sector index to create varied counts: [1, 2, 3, 2, 4, 3]
  const connectionPatterns = [
    [1], // Sector 0: 1 connection (to next)
    [1, -Math.floor(sectors.length / 2)], // Sector 1: 2 connections (next + opposite)
    [1, -1, 2], // Sector 2: 3 connections (next + prev + skipOne)
    [1, -Math.floor(sectors.length / 2)], // Sector 3: 2 connections (next + opposite)
    [1, -1, -Math.floor(sectors.length / 2), 2], // Sector 4: 4 connections
    [1, -1, 2], // Sector 5: 3 connections (next + prev + skipOne)
  ];

  for (let i = 0; i < sectors.length; i++) {
    const pattern = connectionPatterns[i] || [1]; // Default to 1 connection
    if (!sectorResourceUsage.has(i)) {
      sectorResourceUsage.set(i, new Set());
    }

    pattern.forEach((offset) => {
      const targetIndex = (i + offset + sectors.length) % sectors.length;

      // Don't connect to self
      if (targetIndex === i) return;

      // Avoid duplicate connections (check if reverse connection already exists)
      const reverseExists = connections.some((c) => c.from === targetIndex && c.to === i);

      if (!reverseExists) {
        // Assign resource type ensuring variety - cycle through all resource types globally
        // This ensures all resource types (products, services, materials, equipment) are used
        const connectionIndex = connections.length;
        const resourceTypeIndex = connectionIndex % RESOURCE_TYPES.length;

        // Track usage per sector for reference (but don't restrict assignment)
        const usedResources = sectorResourceUsage.get(i)!;
        usedResources.add(resourceTypeIndex);

        connections.push({
          from: i,
          to: targetIndex,
          resourceType: RESOURCE_TYPES[resourceTypeIndex].type,
          strength:
            Math.abs(offset) === 1
              ? 0.8
              : Math.abs(offset) === Math.floor(sectors.length / 2)
                ? 0.5
                : 0.6,
        });
      }
    });
  }

  return connections;
};

const ResourceExchangeVisualization: React.FC<ResourceExchangeVisualizationProps> = ({
  maxItems = 6,
  showStats = false,
}) => {
  const { t } = useTranslation();
  const { sectors: dynamicSectors, isLoading } = useDynamicSectors(maxItems);
  const [hoveredSector, setHoveredSector] = useState<number | null>(null);
  const [activeConnections, setActiveConnections] = useState<Set<string>>(new Set());

  // Create layout calculator instance - uses SVG native coordinate system
  const layoutCalculator = useMemo(() => new LayoutCalculator(LAYOUT_CONFIG.SVG_VIEWBOX_SIZE), []);

  // Generate sector positions using layout calculator
  const sectorPositions = useMemo(() => {
    return layoutCalculator.calculateSectorPositions(dynamicSectors.length);
  }, [dynamicSectors.length, layoutCalculator]);

  // Generate connections between sectors
  const connections = useMemo(() => {
    if (dynamicSectors.length === 0) return [];
    return generateConnections(dynamicSectors);
  }, [dynamicSectors]);

  // Activate connections on hover
  React.useEffect(() => {
    if (hoveredSector !== null) {
      const active = new Set<string>();
      connections.forEach((conn, idx) => {
        if (conn.from === hoveredSector || conn.to === hoveredSector) {
          active.add(`conn-${idx}`);
        }
      });
      setActiveConnections(active);
    } else {
      setActiveConnections(new Set());
    }
  }, [hoveredSector, connections]);

  if (isLoading) {
    return (
      <div className="w-full relative aspect-square max-w-lg mx-auto">
        <div className="absolute inset-0 flex items-center justify-center">
          <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-primary"></div>
        </div>
      </div>
    );
  }

  if (dynamicSectors.length === 0) {
    return null;
  }

  return (
    <div className="w-full flex flex-col items-center gap-4 max-w-lg mx-auto">
      {/* Title */}
      <div className="text-center">
        <h3 className="text-sm font-semibold text-foreground mb-1">Resource Exchange Network</h3>
        <p className="text-xs text-muted-foreground">Businesses connect to exchange resources</p>
      </div>

      {/* SVG Canvas for network visualization */}
      <div className="relative w-full aspect-square min-h-[400px]">
        <svg
          viewBox={`0 0 ${LAYOUT_CONFIG.SVG_VIEWBOX_SIZE} ${LAYOUT_CONFIG.SVG_VIEWBOX_SIZE}`}
          className="w-full h-full"
          preserveAspectRatio="xMidYMid meet"
          style={{ overflow: 'visible' }}
        >
          <defs>
            {/* Gradient for connection lines */}
            <linearGradient id="connectionGradient" x1="0%" y1="0%" x2="100%" y2="0%">
              <stop offset="0%" stopColor="hsl(var(--primary))" stopOpacity="0.3" />
              <stop offset="50%" stopColor="hsl(var(--primary))" stopOpacity="0.6" />
              <stop offset="100%" stopColor="hsl(var(--primary))" stopOpacity="0.3" />
            </linearGradient>

            {/* Glow filter for active connections */}
            <filter id="glow">
              <feGaussianBlur stdDeviation="3" result="coloredBlur" />
              <feMerge>
                <feMergeNode in="coloredBlur" />
                <feMergeNode in="SourceGraphic" />
              </feMerge>
            </filter>
          </defs>

          {/* Connection lines (edges) */}
          <g>
            {connections.map((conn, idx) => {
              const fromPos = sectorPositions[conn.from];
              const toPos = sectorPositions[conn.to];
              if (!fromPos || !toPos) return null;

              const isActive = activeConnections.has(`conn-${idx}`) || hoveredSector === null;

              // Check if this is a bidirectional exchange (both A→B and B→A exist)
              const reverseConnection = connections.find(
                (c) => c.from === conn.to && c.to === conn.from
              );
              const isBidirectional = !!reverseConnection;

              // Calculate resource icon position using layout calculator
              const resourceIconPos = layoutCalculator.calculateResourceIconPosition(
                fromPos,
                toPos,
                isBidirectional,
                conn.from,
                conn.to,
                showStats
              );

              // Calculate connection start position
              const connectionStart = layoutCalculator.calculateConnectionStart(
                fromPos,
                resourceIconPos,
                isBidirectional
              );

              // Calculate total distance for particle animation
              const totalDistance = layoutCalculator.distance(connectionStart, toPos);

              return (
                <g key={`connection-${idx}`}>
                  {/* Connection line - for bidirectional: source to destination (icons at midpoint); for unidirectional: from resource icon to destination */}
                  <motion.line
                    x1={connectionStart.x}
                    y1={connectionStart.y}
                    x2={toPos.x}
                    y2={toPos.y}
                    stroke="hsl(var(--primary))"
                    strokeWidth={isActive ? 2 : 1}
                    strokeDasharray={isActive ? '0' : '4 4'}
                    opacity={isActive ? conn.strength : 0.2}
                    filter={isActive ? 'url(#glow)' : undefined}
                    initial={{ pathLength: 0 }}
                    animate={{ pathLength: isActive ? 1 : 0.3 }}
                    transition={{ duration: 1, delay: idx * 0.1 }}
                  />

                  {/* Animated resource flow particles - flow from resource icon to organization */}
                  {isActive && totalDistance > 0 && (
                    <>
                      {[...Array(3)].map((_, particleIdx) => {
                        // Particles start exactly at the resource icon position
                        const particleStartX = resourceIconPos.x;
                        const particleStartY = resourceIconPos.y;

                        // Particles travel all the way to the organization icon
                        // Stop just before the organization circle edge to avoid overlap
                        const organizationRadius = LAYOUT_CONFIG.SECTOR_NODE_RADIUS;
                        const particleEndX = toPos.x;
                        const particleEndY = toPos.y;

                        // Calculate full distance from resource icon to organization
                        const fullDistance = layoutCalculator.distance(
                          { x: particleStartX, y: particleStartY },
                          { x: particleEndX, y: particleEndY }
                        );

                        // Base duration with randomization for organic feel
                        const baseDuration = 4 + conn.strength * 2;
                        const randomVariation = 0.7 + Math.random() * 0.6; // 0.7x to 1.3x speed variation
                        const particleDuration = baseDuration * randomVariation;

                        // Stagger particles for continuous flow - overlap them so there's always a particle visible
                        // Each particle starts before the previous one finishes (overlap by ~60%)
                        const overlapRatio = 0.6; // 60% overlap
                        const staggerDelay = particleIdx * particleDuration * (1 - overlapRatio);

                        // Randomize particle properties for dynamic feel
                        const particleSize = 2.5 + Math.random() * 1.5; // 2.5-4px radius
                        const particleOpacity = 0.6 + Math.random() * 0.4; // 0.6-1.0 opacity

                        // Slight path variation for more organic movement (small perpendicular offset)
                        const pathVariation = (Math.random() - 0.5) * 4; // Reduced to ±2px for more realistic path
                        const angle = Math.atan2(
                          particleEndY - particleStartY,
                          particleEndX - particleStartX
                        );
                        const perpAngle = angle + Math.PI / 2;
                        const offsetX = Math.cos(perpAngle) * pathVariation;
                        const offsetY = Math.sin(perpAngle) * pathVariation;

                        // Add slight random delay to break synchronization
                        const randomDelay = Math.random() * 0.5;

                        // Wait for connection line to be visible before starting particles
                        // Connection line has delay: idx * 0.1 and duration: 1s
                        const connectionLineDelay = idx * 0.1;
                        const connectionLineDuration = 1;
                        const waitForLine = connectionLineDelay + connectionLineDuration * 0.8; // Start particles when line is 80% visible

                        return (
                          <motion.circle
                            key={`particle-${idx}-${particleIdx}`}
                            r={particleSize}
                            fill="hsl(var(--primary))"
                            initial={{
                              cx: particleStartX + offsetX,
                              cy: particleStartY + offsetY,
                              opacity: particleOpacity, // Start fully visible
                            }}
                            animate={{
                              cx: [particleStartX + offsetX, particleEndX + offsetX],
                              cy: [particleStartY + offsetY, particleEndY + offsetY],
                              opacity: [particleOpacity, particleOpacity, 0], // Stay fully visible, fade out only when reaching destination
                            }}
                            transition={{
                              duration: particleDuration,
                              repeat: Infinity,
                              delay: waitForLine + staggerDelay + randomDelay, // Wait for line to appear first
                              ease: 'linear',
                              times: [0, 0.95, 1], // Fully visible (95%), fade out only at destination (5%)
                            }}
                          />
                        );
                      })}
                    </>
                  )}
                </g>
              );
            })}
          </g>

          {/* Sector nodes */}
          {dynamicSectors.map((sector, index) => {
            const pos = sectorPositions[index];
            if (!pos) return null;

            const isHovered = hoveredSector === index;
            const sectorConnections = connections.filter((c) => c.from === index || c.to === index);

            // Find incoming connections (where this sector is the destination)
            const incomingConnections = connections.filter((c) => c.to === index);

            // Calculate pulse animation synchronized with particle arrivals
            // Particles take (4 + strength * 2) seconds to travel, and we have 3 particles staggered
            const getPulseProps = () => {
              // Don't pulse if no incoming connections or if this sector is hovered
              if (incomingConnections.length === 0 || isHovered) {
                return {};
              }

              // Find active incoming connections (where particles are flowing)
              const activeIncoming = incomingConnections.find((conn) => {
                const connIdx = connections.findIndex(
                  (c) => c.from === conn.from && c.to === conn.to
                );
                const connKey = `conn-${connIdx}`;
                // Connection is active if it's in activeConnections set or if nothing is hovered (all connections active)
                return activeConnections.has(connKey) || hoveredSector === null;
              });

              if (!activeIncoming) return {};

              // Calculate pulse timing based on continuous particle flow
              // With 6 particles overlapping at 60%, particles arrive more frequently
              const baseDuration = 4 + activeIncoming.strength * 2;
              const overlapRatio = 0.6;
              const particleInterval = baseDuration * (1 - overlapRatio); // Time between particle arrivals
              const averageDuration = baseDuration * 0.85; // Average duration accounting for randomization

              // Pulse when particles arrive - more frequent pulses for continuous flow
              // Account for initial spring animation (~0.8s) + delay
              const initialAnimationTime = 0.8 + index * 0.1;
              const pulseDelay = Math.max(0, averageDuration - initialAnimationTime);

              return {
                transition: {
                  duration: 0.3,
                  delay: pulseDelay,
                  repeat: Infinity,
                  repeatDelay: particleInterval - 0.3, // Pulse with each particle arrival
                  ease: 'easeInOut',
                },
              };
            };

            const pulseProps = getPulseProps();

            return (
              <g key={sector.backendName || `sector-${index}`}>
                {/* Connection highlight circle - consistent size */}
                {isHovered && (
                  <motion.circle
                    cx={pos.x}
                    cy={pos.y}
                    r="90"
                    fill="none"
                    stroke="hsl(var(--primary))"
                    strokeWidth="1.5"
                    strokeDasharray="4 8"
                    opacity="0.25"
                    initial={{ scale: 0.9, opacity: 0 }}
                    animate={{ scale: 1.15, opacity: 0.3 }}
                    transition={{ duration: 2, repeat: Infinity, ease: 'easeInOut' }}
                  />
                )}

                {/* Sector node circle - consistent size */}
                <motion.circle
                  cx={pos.x}
                  cy={pos.y}
                  r="32"
                  fill={`hsl(var(--sector-${sector.colorKey}))`}
                  fillOpacity="0.15"
                  stroke={`hsl(var(--sector-${sector.colorKey}))`}
                  strokeWidth={isHovered ? 3 : 2}
                  filter={isHovered ? 'url(#glow)' : undefined}
                  initial={{ scale: 0 }}
                  animate={
                    Object.keys(pulseProps).length > 0
                      ? {
                          scale: [1, 1.2, 1],
                        }
                      : { scale: 1 }
                  }
                  transition={
                    Object.keys(pulseProps).length > 0
                      ? {
                          scale: {
                            ...pulseProps.transition,
                          },
                          default: {
                            type: 'spring',
                            stiffness: 200,
                            damping: 15,
                            delay: index * 0.1,
                          },
                        }
                      : {
                          type: 'spring',
                          stiffness: 200,
                          damping: 15,
                          delay: index * 0.1,
                        }
                  }
                  onHoverStart={() => setHoveredSector(index)}
                  onHoverEnd={() => setHoveredSector(null)}
                  className="cursor-pointer"
                />

                {/* Sector icon circle background - consistent size */}
                <motion.circle
                  cx={pos.x}
                  cy={pos.y}
                  r="22"
                  fill="hsl(var(--background))"
                  stroke={`hsl(var(--sector-${sector.colorKey}))`}
                  strokeWidth="2"
                  initial={{ scale: 0 }}
                  animate={
                    Object.keys(pulseProps).length > 0
                      ? {
                          scale: [1, 1.2, 1],
                        }
                      : { scale: 1 }
                  }
                  transition={
                    Object.keys(pulseProps).length > 0
                      ? {
                          scale: {
                            ...pulseProps.transition,
                          },
                          default: {
                            delay: index * 0.1 + 0.2,
                          },
                        }
                      : { delay: index * 0.1 + 0.2 }
                  }
                />

                {/* Sector label */}
                <motion.text
                  x={pos.x}
                  y={pos.y + 55}
                  textAnchor="middle"
                  fontSize="12"
                  fill="hsl(var(--foreground))"
                  fontWeight="600"
                  initial={{ opacity: 0 }}
                  animate={{ opacity: 1 }}
                  transition={{ delay: index * 0.1 + 0.3 }}
                >
                  {t(`${sector.nameKey}.name`)}
                </motion.text>

                {/* Connection count badge - shows number of connections */}
                {showStats && sectorConnections.length > 0 && (
                  <g>
                    {/* Background circle - colored by sector */}
                    <motion.circle
                      cx={pos.x + 28}
                      cy={pos.y - 28}
                      r="14"
                      fill={`hsl(var(--sector-${sector.colorKey}))`}
                      stroke="hsl(var(--card))"
                      strokeWidth="2"
                      initial={{ scale: 0 }}
                      animate={{ scale: 1 }}
                      transition={{ delay: index * 0.1 + 0.4 }}
                    />
                    {/* Connection count text - use black for contrast on colored sector backgrounds */}
                    <motion.text
                      x={pos.x + 28}
                      y={pos.y - 28}
                      textAnchor="middle"
                      dominantBaseline="central"
                      fontSize="11"
                      fontWeight="700"
                      fill="black"
                      initial={{ opacity: 0 }}
                      animate={{ opacity: 1 }}
                      transition={{ delay: index * 0.1 + 0.5 }}
                    >
                      {sectorConnections.length}
                    </motion.text>
                    <title>{sectorConnections.length} resource exchange connections</title>
                  </g>
                )}
              </g>
            );
          })}
          {/* Sector icons using foreignObject - native SVG coordinate system */}
          {dynamicSectors.map((sector, index) => {
            const pos = sectorPositions[index];
            if (!pos) return null;

            const bounds = layoutCalculator.getForeignObjectBounds(pos.x, pos.y, 44);

            return (
              <foreignObject
                key={`icon-${sector.backendName || index}`}
                x={bounds.x}
                y={bounds.y}
                width={bounds.width}
                height={bounds.height}
                style={{ overflow: 'visible' }}
              >
                <motion.div
                  className="flex items-center justify-center w-full h-full rounded-full bg-background border-2 pointer-events-none"
                  style={{
                    borderColor: `hsl(var(--sector-${sector.colorKey}))`,
                  }}
                  initial={{ scale: 0, opacity: 0 }}
                  animate={{ scale: 1, opacity: 1 }}
                  transition={{ delay: index * 0.1 + 0.2 }}
                >
                  {React.cloneElement(sector.icon, {
                    className: `w-5 h-5 text-sector-${sector.colorKey}`,
                  })}
                </motion.div>
              </foreignObject>
            );
          })}
          {/* Resource type icons using foreignObject - native SVG coordinate system */}
          {connections.map((conn, idx) => {
            const fromPos = sectorPositions[conn.from];
            const toPos = sectorPositions[conn.to];
            if (!fromPos || !toPos) return null;

            const sourceSector = dynamicSectors[conn.from];
            if (!sourceSector) return null;

            const isActive = activeConnections.has(`conn-${idx}`) || hoveredSector === null;
            const resourceType = RESOURCE_TYPES.find((r) => r.type === conn.resourceType);
            if (!resourceType) return null;

            const ResourceIcon = resourceType.icon;

            // Check if this is a bidirectional exchange (both A→B and B→A exist)
            const reverseConnection = connections.find(
              (c) => c.from === conn.to && c.to === conn.from
            );
            const isBidirectional = !!reverseConnection;

            // Calculate resource icon position using layout calculator
            const resourceIconPos = layoutCalculator.calculateResourceIconPosition(
              fromPos,
              toPos,
              isBidirectional,
              conn.from,
              conn.to,
              showStats
            );

            const bounds = layoutCalculator.getForeignObjectBounds(
              resourceIconPos.x,
              resourceIconPos.y,
              28
            );

            return (
              <foreignObject
                key={`resource-icon-${idx}`}
                x={bounds.x}
                y={bounds.y}
                width={bounds.width}
                height={bounds.height}
                style={{ overflow: 'visible' }}
              >
                <motion.div
                  className="flex items-center justify-center w-full h-full rounded-full bg-background border-2 pointer-events-none shadow-md"
                  style={{
                    borderColor: `hsl(var(--sector-${sourceSector.colorKey}))`,
                  }}
                  initial={{ opacity: 0, scale: 0 }}
                  animate={{
                    opacity: isActive ? 1 : 0,
                    scale: isActive ? 1 : 0,
                  }}
                  transition={{ duration: 0.3 }}
                >
                  <ResourceIcon className={`w-4 h-4 ${resourceType.color}`} />
                </motion.div>
              </foreignObject>
            );
          })}
        </svg>
      </div>

      {/* Legend - moved below the animation */}
      <div className="flex gap-4 items-center bg-background/80 backdrop-blur-sm px-4 py-2 rounded-full border shadow-lg">
        <span className="text-xs text-muted-foreground font-medium">Resource Exchanges:</span>
        {RESOURCE_TYPES.map((resource) => {
          const Icon = resource.icon;
          return (
            <div key={resource.type} className="flex items-center gap-1.5">
              <Icon className={`w-3 h-3 ${resource.color}`} />
              <span className="text-xs text-muted-foreground capitalize">{resource.type}</span>
            </div>
          );
        })}
      </div>
    </div>
  );
};

export default React.memo(ResourceExchangeVisualization);
