"use client"

import { useEffect, useRef } from "react"

interface HyphalNode {
  x: number
  y: number
  vx: number
  vy: number
  age: number
  maxAge: number
  branches: HyphalNode[]
  parent: HyphalNode | null
  angle: number
  angleChangeRate: number
  connections: HyphalNode[]
  opacity: number
  isPersistent: boolean
  createdAt: number
  connectionDensity: number
}

export function HyphalCanvas() {
  const canvasRef = useRef<HTMLCanvasElement>(null)
  const nodesRef = useRef<HyphalNode[]>([])
  const mouseRef = useRef({ x: 0, y: 0, isMoving: false })
  const animationRef = useRef<number>()

  const getDensityColor = (density: number, opacity: number): string => {
    // Map density (0-10+) to hue (0-300 degrees)
    // Low density = red/orange (0-60), high density = blue/violet (240-300)
    const normalizedDensity = Math.min(density / 10, 1)
    const hue = normalizedDensity * 300
    // Muted colors: lower saturation (40-50%) and medium lightness (50-60%)
    const saturation = 40 + normalizedDensity * 10
    const lightness = 50 + normalizedDensity * 10
    return `hsla(${hue}, ${saturation}%, ${lightness}%, ${opacity})`
  }

  useEffect(() => {
    const canvas = canvasRef.current
    if (!canvas) return

    const ctx = canvas.getContext("2d")
    if (!ctx) return

    const resizeCanvas = () => {
      canvas.width = window.innerWidth
      canvas.height = window.innerHeight
    }
    resizeCanvas()
    window.addEventListener("resize", resizeCanvas)

    let mouseMoveTimeout: NodeJS.Timeout
    const handleMouseMove = (e: MouseEvent) => {
      mouseRef.current = { x: e.clientX, y: e.clientY, isMoving: true }
      clearTimeout(mouseMoveTimeout)
      mouseMoveTimeout = setTimeout(() => {
        mouseRef.current.isMoving = false
      }, 100)
    }
    window.addEventListener("mousemove", handleMouseMove)

    const createNode = (x: number, y: number, parent: HyphalNode | null = null): HyphalNode => {
      const angle = parent ? parent.angle + (Math.random() - 0.5) * 1.2 : Math.random() * Math.PI * 2
      const speed = parent ? 1.5 + Math.random() * 1 : 2 + Math.random() * 2
      return {
        x,
        y,
        vx: Math.cos(angle) * speed,
        vy: Math.sin(angle) * speed,
        age: 0,
        maxAge: 80 + Math.random() * 60,
        branches: [],
        parent,
        angle,
        angleChangeRate: (Math.random() - 0.5) * 0.2,
        connections: [],
        opacity: 1,
        isPersistent: false,
        createdAt: Date.now(),
        connectionDensity: 0,
      }
    }

    const findNearbyPersistentNodes = (x: number, y: number, radius: number): HyphalNode[] => {
      return nodesRef.current.filter((node) => {
        if (!node.isPersistent) return false
        const dx = node.x - x
        const dy = node.y - y
        const distance = Math.sqrt(dx * dx + dy * dy)
        return distance < radius
      })
    }

    const createMeshConnections = () => {
      nodesRef.current.forEach((node, i) => {
        const maturityFactor = node.age / node.maxAge
        const maxConnections = node.isPersistent ? 7 : maturityFactor > 0.6 ? 4 : 2
        const connectionDistance = maturityFactor > 0.6 ? 80 : 50
        const connectionProbability = maturityFactor > 0.6 ? 0.97 : 0.99

        if (node.age < 20 || node.connections.length >= maxConnections) return

        for (let j = i + 1; j < nodesRef.current.length; j++) {
          const other = nodesRef.current[j]
          if (other === node.parent || node === other.parent) continue

          const otherMaturityFactor = other.age / other.maxAge
          const otherMaxConnections = other.isPersistent ? 7 : otherMaturityFactor > 0.6 ? 4 : 2

          if (other.age < 20 || other.connections.length >= otherMaxConnections) continue

          const dx = other.x - node.x
          const dy = other.y - node.y
          const distance = Math.sqrt(dx * dx + dy * dy)

          if (distance < connectionDistance && Math.random() > connectionProbability) {
            if (!node.connections.includes(other)) {
              node.connections.push(other)
              other.connections.push(node)
            }
          }
        }
      })
    }

    const drawBranchingConnection = (
      ctx: CanvasRenderingContext2D,
      x1: number,
      y1: number,
      x2: number,
      y2: number,
      opacity: number,
      color: string,
      fragmentationFactor: number,
    ) => {
      const dx = x2 - x1
      const dy = y2 - y1
      const distance = Math.sqrt(dx * dx + dy * dy)

      if (fragmentationFactor > 0.5 && Math.random() > fragmentationFactor) {
        // Skip drawing some connections to create fragmentation effect
        return
      }

      if (distance < 30) {
        ctx.beginPath()
        ctx.moveTo(x1, y1)
        ctx.lineTo(x2, y2)
        ctx.stroke()
        return
      }

      const numBranches = distance > 60 ? 2 : 1
      const points = [{ x: x1, y: y1 }]

      for (let i = 0; i < numBranches; i++) {
        const t = (i + 1) / (numBranches + 1)
        const midX = x1 + dx * t
        const midY = y1 + dy * t
        const perpX = -dy / distance
        const perpY = dx / distance
        const offset = (Math.random() - 0.5) * distance * 0.3
        points.push({
          x: midX + perpX * offset,
          y: midY + perpY * offset,
        })
      }

      points.push({ x: x2, y: y2 })

      ctx.beginPath()
      ctx.moveTo(points[0].x, points[0].y)

      for (let i = 1; i < points.length - 1; i++) {
        const xc = (points[i].x + points[i + 1].x) / 2
        const yc = (points[i].y + points[i + 1].y) / 2
        ctx.quadraticCurveTo(points[i].x, points[i].y, xc, yc)
      }

      ctx.lineTo(points[points.length - 1].x, points[points.length - 1].y)
      ctx.stroke()
    }

    const animate = () => {
      ctx.fillStyle = "rgba(250, 248, 245, 0.08)"
      ctx.fillRect(0, 0, canvas.width, canvas.height)

      const currentTime = Date.now()

      if (mouseRef.current.isMoving && Math.random() > 0.65) {
        const burstCount = Math.floor(Math.random() * 2) + 1
        const nearbyPersistent = findNearbyPersistentNodes(mouseRef.current.x, mouseRef.current.y, 100)

        for (let i = 0; i < burstCount; i++) {
          const node = createNode(mouseRef.current.x, mouseRef.current.y)
          nodesRef.current.push(node)

          if (nearbyPersistent.length > 0) {
            const connectCount = Math.min(3, nearbyPersistent.length)
            for (let j = 0; j < connectCount; j++) {
              const target = nearbyPersistent[Math.floor(Math.random() * nearbyPersistent.length)]
              if (!node.connections.includes(target)) {
                node.connections.push(target)
                target.connections.push(node)
              }
            }
          }
        }
      }

      if (Math.random() > 0.85) {
        createMeshConnections()
      }

      nodesRef.current.forEach((node) => {
        node.connectionDensity = node.connections.length
      })

      nodesRef.current = nodesRef.current.filter((node) => {
        node.age++

        const timeSinceCreation = currentTime - node.createdAt
        const fadeOutDuration = 30000 // 30 seconds
        const fadeOutFactor = Math.min(timeSinceCreation / fadeOutDuration, 1)

        if (!node.isPersistent) {
          node.angle += node.angleChangeRate
          if (Math.random() > 0.92) {
            node.angleChangeRate = (Math.random() - 0.5) * 0.25
          }
          if (Math.random() > 0.96) {
            node.angle += (Math.random() - 0.5) * 0.8
          }

          const speed = Math.sqrt(node.vx * node.vx + node.vy * node.vy)
          node.vx = Math.cos(node.angle) * speed
          node.vy = Math.sin(node.angle) * speed

          node.x += node.vx
          node.y += node.vy

          node.vx *= 0.96
          node.vy *= 0.96
        }

        const ageFactor = node.age / node.maxAge
        if (node.isPersistent) {
          node.opacity = Math.max(0, 0.15 * (1 - fadeOutFactor))
        } else if (ageFactor >= 1) {
          node.isPersistent = true
          node.opacity = 0.15 * (1 - fadeOutFactor)
          node.vx = 0
          node.vy = 0
        } else {
          node.opacity = Math.max(0, (1 - ageFactor * 0.85) * (1 - fadeOutFactor * 0.5))
        }

        if (fadeOutFactor >= 1) {
          return false
        }

        if (
          node.age > 8 &&
          node.age < node.maxAge - 30 &&
          Math.random() > 0.92 &&
          node.branches.length < 4 &&
          !node.isPersistent
        ) {
          const branch = createNode(node.x, node.y, node)
          node.branches.push(branch)
          nodesRef.current.push(branch)
        }

        if (node.parent) {
          const avgDensity = (node.connectionDensity + node.parent.connectionDensity) / 2
          const parentOpacity = node.parent.opacity * 0.5
          const nodeOpacity = node.opacity * 0.5

          const gradient = ctx.createLinearGradient(node.parent.x, node.parent.y, node.x, node.y)
          gradient.addColorStop(0, getDensityColor(node.parent.connectionDensity, parentOpacity))
          gradient.addColorStop(0.5, getDensityColor(avgDensity, (parentOpacity + nodeOpacity) / 2))
          gradient.addColorStop(1, getDensityColor(node.connectionDensity, nodeOpacity))

          ctx.strokeStyle = gradient
          ctx.lineWidth = 2.5 + Math.random() * 1.5
          ctx.lineCap = "round"
          ctx.beginPath()
          ctx.moveTo(node.parent.x, node.parent.y)
          ctx.lineTo(node.x, node.y)
          ctx.stroke()
        }

        node.connections.forEach((connected) => {
          if (nodesRef.current.includes(connected)) {
            const avgDensity = (node.connectionDensity + connected.connectionDensity) / 2
            const avgOpacity = ((node.opacity + connected.opacity) / 2) * 0.35

            // Calculate fragmentation based on time
            const nodeFragmentation = Math.min((currentTime - node.createdAt) / fadeOutDuration, 1)
            const connectedFragmentation = Math.min((currentTime - connected.createdAt) / fadeOutDuration, 1)
            const avgFragmentation = (nodeFragmentation + connectedFragmentation) / 2

            ctx.strokeStyle = getDensityColor(avgDensity, avgOpacity)
            ctx.lineWidth = 1.5
            ctx.lineCap = "round"
            drawBranchingConnection(
              ctx,
              node.x,
              node.y,
              connected.x,
              connected.y,
              avgOpacity,
              ctx.strokeStyle,
              avgFragmentation,
            )
          }
        })

        ctx.fillStyle = getDensityColor(node.connectionDensity, node.opacity * 0.7)
        ctx.beginPath()
        ctx.arc(node.x, node.y, 2.5, 0, Math.PI * 2)
        ctx.fill()

        return node.isPersistent || node.age < node.maxAge
      })

      if (nodesRef.current.length > 800) {
        const persistentNodes = nodesRef.current.filter((n) => n.isPersistent)
        const activeNodes = nodesRef.current.filter((n) => !n.isPersistent)
        if (persistentNodes.length > 500) {
          nodesRef.current = [...persistentNodes.slice(-400), ...activeNodes]
        }
      }

      animationRef.current = requestAnimationFrame(animate)
    }

    animate()

    return () => {
      window.removeEventListener("resize", resizeCanvas)
      window.removeEventListener("mousemove", handleMouseMove)
      if (animationRef.current) {
        cancelAnimationFrame(animationRef.current)
      }
    }
  }, [])

  return <canvas ref={canvasRef} className="fixed inset-0 pointer-events-none z-10" style={{ opacity: 0.6 }} />
}
