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

export type EdgeState = 'default' | 'downstream' | 'upstream' | 'crossref'

export interface GlowEdgeData {
  edgeState?: EdgeState
  label?: string
  [key: string]: unknown
}

const EDGE_CONFIGS: Record<EdgeState, {
  gradientId: string
  strokeWidth: number
  filterClass: string
  animationClass: string
}> = {
  default: {
    gradientId: 'edge-gradient-default',
    strokeWidth: 1.5,
    filterClass: 'glow-edge-default',
    animationClass: '',
  },
  downstream: {
    gradientId: 'edge-gradient-downstream',
    strokeWidth: 2,
    filterClass: 'glow-edge-downstream',
    animationClass: 'glow-edge-flow-downstream',
  },
  upstream: {
    gradientId: 'edge-gradient-upstream',
    strokeWidth: 2,
    filterClass: 'glow-edge-upstream',
    animationClass: 'glow-edge-flow-upstream',
  },
  crossref: {
    gradientId: 'edge-gradient-downstream',
    strokeWidth: 2,
    filterClass: 'glow-edge-downstream',
    animationClass: 'glow-edge-flow-downstream',
  },
}

/** Shared SVG <defs> — render once inside the ReactFlow container. */
export function GlowEdgeDefs() {
  return (
    <svg style={{ position: 'absolute', width: 0, height: 0 }}>
      <defs>
        {/* Default: subtle white/gray */}
        <linearGradient id="edge-gradient-default" x1="0%" y1="0%" x2="0%" y2="100%">
          <stop offset="0%" stopColor="rgba(255,255,255,0.25)" />
          <stop offset="100%" stopColor="rgba(255,255,255,0.08)" />
        </linearGradient>

        {/* Downstream: accent brand */}
        <linearGradient id="edge-gradient-downstream" x1="0%" y1="0%" x2="0%" y2="100%">
          <stop offset="0%" stopColor="#3b82f6" />
          <stop offset="100%" stopColor="#60a5fa" />
        </linearGradient>

        {/* Upstream: amber */}
        <linearGradient id="edge-gradient-upstream" x1="0%" y1="100%" x2="0%" y2="0%">
          <stop offset="0%" stopColor="#f59e0b" />
          <stop offset="100%" stopColor="#fbbf24" />
        </linearGradient>

        {/* Glow filters */}
        <filter id="glow-default" x="-20%" y="-20%" width="140%" height="140%">
          <feGaussianBlur in="SourceGraphic" stdDeviation="1.5" result="blur" />
          <feMerge>
            <feMergeNode in="blur" />
            <feMergeNode in="SourceGraphic" />
          </feMerge>
        </filter>
        <filter id="glow-accent" x="-30%" y="-30%" width="160%" height="160%">
          <feGaussianBlur in="SourceGraphic" stdDeviation="3" result="blur" />
          <feMerge>
            <feMergeNode in="blur" />
            <feMergeNode in="SourceGraphic" />
          </feMerge>
        </filter>
        <filter id="glow-amber" x="-30%" y="-30%" width="160%" height="160%">
          <feGaussianBlur in="SourceGraphic" stdDeviation="3" result="blur" />
          <feMerge>
            <feMergeNode in="blur" />
            <feMergeNode in="SourceGraphic" />
          </feMerge>
        </filter>
      </defs>
    </svg>
  )
}

function GlowEdgeComponent({
  id,
  sourceX,
  sourceY,
  targetX,
  targetY,
  sourcePosition,
  targetPosition,
  data,
  label,
  labelStyle,
  labelBgStyle,
  markerEnd,
}: EdgeProps) {
  const edgeState = (data as GlowEdgeData)?.edgeState ?? 'default'
  const config = EDGE_CONFIGS[edgeState]
  const isCrossref = edgeState === 'crossref'

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

  const filterId = edgeState === 'default' ? 'glow-default'
    : edgeState === 'upstream' ? 'glow-amber'
    : 'glow-accent'

  return (
    <>
      {/* Glow layer (wider, blurred) */}
      <path
        d={edgePath}
        fill="none"
        stroke={`url(#${config.gradientId})`}
        strokeWidth={config.strokeWidth + 2}
        filter={`url(#${filterId})`}
        opacity={edgeState === 'default' ? 0.3 : 0.5}
        className="pointer-events-none"
      />

      {/* Main edge path */}
      <BaseEdge
        id={id}
        path={edgePath}
        style={{
          stroke: `url(#${config.gradientId})`,
          strokeWidth: config.strokeWidth,
          strokeDasharray: isCrossref ? '6 3' : undefined,
        }}
        className={config.animationClass || undefined}
        markerEnd={markerEnd}
      />

      {/* Animated dash overlay for downstream/upstream */}
      {(edgeState === 'downstream' || edgeState === 'upstream' || isCrossref) && (
        <path
          d={edgePath}
          fill="none"
          stroke={`url(#${config.gradientId})`}
          strokeWidth={config.strokeWidth}
          strokeDasharray="8 12"
          className={config.animationClass}
          opacity={0.9}
        />
      )}

      {/* Label */}
      {label && (
        <g transform={`translate(${labelX}, ${labelY})`}>
          <rect
            x={-((String(label).length * 5.5 + 8) / 2)}
            y={-9}
            width={String(label).length * 5.5 + 8}
            height={18}
            rx={4}
            style={labelBgStyle as React.CSSProperties ?? { fill: 'var(--color-card)', fillOpacity: 0.9 }}
          />
          <text
            textAnchor="middle"
            dominantBaseline="central"
            style={labelStyle as React.CSSProperties ?? { fill: 'var(--color-muted-foreground)', fontSize: 11 }}
          >
            {String(label)}
          </text>
        </g>
      )}
    </>
  )
}

export const GlowEdge = memo(GlowEdgeComponent)
