import React, { memo } from 'react'
import {
  BaseEdge,
  getBezierPath,
  type EdgeProps,
} from '@xyflow/react'
import { useCanvasStore } from '@/app/canvas/canvasStore'
import { selectConnectionStatusForEdge } from '@/app/canvas/canvasStore.selectors'
import { CONNECTION_STATUS_CLASS } from '@/lib/graph/connectionStatus'
import { getConnectionLabelForTargetAndStatus } from '@/lib/graph/nodeRegistry'

const EDGE_STROKE_WIDTH = 2
const DOT_MARKER_R = 1.5

function AnimatedEdgeInner({
  id,
  source,
  sourceX,
  sourceY,
  targetX,
  targetY,
  sourcePosition,
  targetPosition,
  style,
  label: labelProp,
  interactionWidth,
  target,
  data,
}: EdgeProps) {
  const connectionStatus = useCanvasStore((s) =>
    selectConnectionStatusForEdge(s, source, target)
  )
  const statusClass = CONNECTION_STATUS_CLASS[connectionStatus]

  const targetType = (data as { targetType?: string } | undefined)?.targetType ?? ''
  const dataLabel = (data as { connectionLabel?: string } | undefined)?.connectionLabel
  const displayLabel =
    getConnectionLabelForTargetAndStatus(targetType, connectionStatus) ?? labelProp ?? dataLabel

  const [edgePath, edgeLabelX, edgeLabelY] = getBezierPath({
    sourceX,
    sourceY,
    targetX,
    targetY,
    sourcePosition,
    targetPosition,
  })

  const startId = `animated-edge-dot-start-${id}`
  const endId = `animated-edge-dot-end-${id}`

  return (
    <>
      <defs>
        <marker
          id={startId}
          markerWidth={DOT_MARKER_R * 2}
          markerHeight={DOT_MARKER_R * 2}
          refX={DOT_MARKER_R - 1}
          refY={DOT_MARKER_R}
          orient="auto"
        >
          <circle
            r={DOT_MARKER_R}
            cx={DOT_MARKER_R}
            cy={DOT_MARKER_R}
            className="fill-primary"
            strokeWidth={2}
          />
        </marker>
        <marker
          id={endId}
          markerWidth={DOT_MARKER_R * 2}
          markerHeight={DOT_MARKER_R * 2}
          refX={DOT_MARKER_R + 1}
          refY={DOT_MARKER_R}
          orient="auto"
        >
          <circle
            r={DOT_MARKER_R}
            cx={DOT_MARKER_R}
            cy={DOT_MARKER_R}
            className="fill-primary"
            strokeWidth={2}
          />
        </marker>
      </defs>
      <BaseEdge
        path={edgePath}
        markerStart={`url(#${startId})`}
        markerEnd={`url(#${endId})`}
        style={{
          strokeWidth: EDGE_STROKE_WIDTH,
          ...style,
        }}
        className={`animated-edge-path${statusClass ? ` ${statusClass}` : ''}`}
        interactionWidth={interactionWidth}
      />
      {displayLabel != null && displayLabel !== '' && (
        <g transform={`translate(${edgeLabelX}, ${edgeLabelY})`} className="nodrag nopan">
          <rect
            x={-32}
            y={-9}
            width={64}
            height={18}
            rx={4}
            ry={4}
            className="fill-background stroke-border"
            strokeWidth={1}
          />
          <text
            textAnchor="middle"
            dominantBaseline="middle"
            className="fill-foreground text-[10px] font-medium"
          >
            {displayLabel}
          </text>
        </g>
      )}
    </>
  )
}
function edgePropsAreEqual(prev: EdgeProps, next: EdgeProps): boolean {
  return (
    prev.id === next.id &&
    prev.source === next.source &&
    prev.target === next.target &&
    prev.sourceX === next.sourceX &&
    prev.sourceY === next.sourceY &&
    prev.targetX === next.targetX &&
    prev.targetY === next.targetY &&
    prev.sourcePosition === next.sourcePosition &&
    prev.targetPosition === next.targetPosition &&
    prev.style === next.style &&
    prev.label === next.label &&
    (prev.data as { connectionLabel?: string; targetType?: string } | undefined)?.connectionLabel ===
      (next.data as { connectionLabel?: string; targetType?: string } | undefined)?.connectionLabel &&
    (prev.data as { targetType?: string } | undefined)?.targetType ===
      (next.data as { targetType?: string } | undefined)?.targetType
  )
}

export const AnimatedEdge = memo(AnimatedEdgeInner, edgePropsAreEqual)

