import { memo } from 'react'
import {
  BaseEdge,
  getSmoothStepPath,
  getStraightPath,
  getBezierPath,
  type EdgeProps,
} from '@xyflow/react'

interface AnimatedEdgeData {
  connectionType?: string
  duration?: number
  direction?: 'forward' | 'reverse' | 'alternate' | 'alternate-reverse'
  path?: 'bezier' | 'smoothstep' | 'step' | 'straight'
  repeat?: number | 'indefinite'
  shape?: 'circle' | 'package'
  speed?: string | null
  notes?: string | null
  [key: string]: unknown
}

const CONNECTION_COLORS: Record<string, string> = {
  ethernet: '#60a5fa',
  fiber: '#34d399',
  wifi: '#a78bfa',
  vpn: '#eab308',
  vlan: '#848b9b',
  wan: '#f87171',
}

const DEFAULT_COLOR = '#848b9b'

function getPath(
  props: EdgeProps,
  pathType: string,
): [string, number, number] {
  const params = {
    sourceX: props.sourceX,
    sourceY: props.sourceY,
    sourcePosition: props.sourcePosition,
    targetX: props.targetX,
    targetY: props.targetY,
    targetPosition: props.targetPosition,
  }

  switch (pathType) {
    case 'bezier': {
      const [path, labelX, labelY] = getBezierPath(params)
      return [path, labelX, labelY]
    }
    case 'straight': {
      const [path, labelX, labelY] = getStraightPath(params)
      return [path, labelX, labelY]
    }
    default: {
      const [path, labelX, labelY] = getSmoothStepPath(params)
      return [path, labelX, labelY]
    }
  }
}

function getAnimateMotionProps(data: AnimatedEdgeData) {
  const duration = data.duration ?? 2
  const direction = data.direction ?? 'forward'
  const repeat = data.repeat ?? 'indefinite'

  const keyPoints: Record<string, string> = {
    forward: '0;1',
    reverse: '1;0',
    alternate: '0;1',
    'alternate-reverse': '1;0',
  }

  return {
    dur: `${duration}s`,
    repeatCount: String(repeat),
    keyPoints: keyPoints[direction] || '0;1',
    keyTimes: '0;1',
  }
}

function AnimatedSvgEdgeComponent(props: EdgeProps) {
  const data = (props.data || {}) as AnimatedEdgeData
  const connectionType = data.connectionType || 'ethernet'
  const color = CONNECTION_COLORS[connectionType] || DEFAULT_COLOR
  const pathType = data.path ?? 'smoothstep'
  const shape = data.shape ?? 'circle'

  const [edgePath] = getPath(props, pathType)
  const motionProps = getAnimateMotionProps(data)

  return (
    <>
      <BaseEdge
        path={edgePath}
        style={{
          stroke: color,
          strokeWidth: props.selected ? 3 : 2,
          ...(connectionType === 'wifi' || connectionType === 'wan' || connectionType === 'vpn'
            ? { strokeDasharray: connectionType === 'wifi' ? '3,3' : '8,4' }
            : {}),
        }}
      />
      <circle r={0} fill={color}>
        <animateMotion
          path={edgePath}
          calcMode="linear"
          {...motionProps}
        />
        <animate
          attributeName="r"
          values="0;3;3;3;0"
          keyTimes="0;0.05;0.5;0.95;1"
          dur={motionProps.dur}
          repeatCount={motionProps.repeatCount}
        />
      </circle>
      {shape === 'package' && (
        <rect x={-4} y={-4} width={8} height={8} rx={2} fill={color} opacity={0.8}>
          <animateMotion
            path={edgePath}
            calcMode="linear"
            {...motionProps}
          />
        </rect>
      )}
    </>
  )
}

export const AnimatedSvgEdge = memo(AnimatedSvgEdgeComponent)
