import { useEffect, useRef } from 'react'

import { cn } from './utils'
import { NetworkGraph as NetworkGraphVanilla } from '../../visualization/network-graph'
import type {
  GraphNode,
  GraphEdge,
  NetworkGraphConfig,
} from '../../visualization/network-graph/types'

export type { GraphNode, GraphEdge } from '../../visualization/network-graph/types'

export interface NetworkGraphProps {
  nodes: GraphNode[]
  edges: GraphEdge[]
  layout?: 'force' | 'circular' | 'grid'
  zoomable?: boolean
  pannable?: boolean
  nodeRadius?: number
  showLabels?: boolean
  onNodeClick?: (node: GraphNode) => void
  onEdgeClick?: (edge: GraphEdge) => void
  className?: string
}

function NetworkGraph({
  nodes,
  edges,
  layout = 'force',
  zoomable = true,
  pannable = true,
  nodeRadius,
  showLabels = true,
  onNodeClick,
  onEdgeClick,
  className,
}: NetworkGraphProps) {
  const containerRef = useRef<HTMLDivElement>(null)
  const instanceRef = useRef<NetworkGraphVanilla | null>(null)

  const onNodeClickRef = useRef(onNodeClick)
  onNodeClickRef.current = onNodeClick
  const onEdgeClickRef = useRef(onEdgeClick)
  onEdgeClickRef.current = onEdgeClick

  useEffect(() => {
    const container = containerRef.current
    if (!container) return

    const cfg: NetworkGraphConfig = {
      container,
      nodes,
      edges,
      layout,
      zoomable,
      pannable,
      showLabels,
      onNodeClick: node => onNodeClickRef.current?.(node),
      onEdgeClick: edge => onEdgeClickRef.current?.(edge),
    }
    if (nodeRadius !== undefined) cfg.nodeRadius = nodeRadius

    instanceRef.current = new NetworkGraphVanilla(cfg)

    return () => {
      instanceRef.current?.destroy()
      instanceRef.current = null
    }
  }, [zoomable, pannable, nodeRadius, showLabels])

  // Update data
  useEffect(() => {
    if (instanceRef.current) {
      instanceRef.current.update(nodes, edges)
    }
  }, [nodes, edges])

  // Update layout
  useEffect(() => {
    if (instanceRef.current) {
      instanceRef.current.setLayout(layout)
    }
  }, [layout])

  return (
    <div
      ref={containerRef}
      data-slot="network-graph"
      className={cn('relative h-full w-full overflow-hidden', className)}
    />
  )
}
NetworkGraph.displayName = 'NetworkGraph'

export { NetworkGraph }
