import { useRef, useEffect, useCallback } from "react";

interface Node {
  x: number;
  y: number;
  connections: number[];
  glow: number;
}

interface Pulse {
  fromNode: number;
  toNode: number;
  progress: number;
  speed: number;
  alpha: number;
}

const NeuralCanvas = () => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const mouse = useRef({ x: -1000, y: -1000 });
  const nodes = useRef<Node[]>([]);
  const pulses = useRef<Pulse[]>([]);
  const dpr = useRef(1);

  const buildCircuit = useCallback((w: number, h: number) => {
    const spacing = 80;
    const cols = Math.ceil(w / spacing) + 1;
    const rows = Math.ceil(h / spacing) + 1;
    const nodeList: Node[] = [];

    // Create grid nodes with slight randomness
    for (let r = 0; r < rows; r++) {
      for (let c = 0; c < cols; c++) {
        nodeList.push({
          x: c * spacing + (Math.random() - 0.5) * 12,
          y: r * spacing + (Math.random() - 0.5) * 12,
          connections: [],
          glow: 0,
        });
      }
    }

    // Create circuit-style connections (right-angle paths)
    for (let r = 0; r < rows; r++) {
      for (let c = 0; c < cols; c++) {
        const idx = r * cols + c;
        // Horizontal connection (skip some randomly for circuit look)
        if (c < cols - 1 && Math.random() > 0.25) {
          nodeList[idx].connections.push(idx + 1);
          nodeList[idx + 1].connections.push(idx);
        }
        // Vertical connection
        if (r < rows - 1 && Math.random() > 0.3) {
          nodeList[idx].connections.push(idx + cols);
          nodeList[idx + cols].connections.push(idx);
        }
      }
    }

    // Deduplicate connections
    nodeList.forEach((n) => {
      n.connections = [...new Set(n.connections)];
    });

    nodes.current = nodeList;
  }, []);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    if (!ctx) return;

    dpr.current = Math.min(window.devicePixelRatio || 1, 2);

    const resize = () => {
      const rect = canvas.getBoundingClientRect();
      canvas.width = rect.width * dpr.current;
      canvas.height = rect.height * dpr.current;
      ctx.setTransform(dpr.current, 0, 0, dpr.current, 0, 0);
      buildCircuit(rect.width, rect.height);
    };
    resize();
    window.addEventListener("resize", resize);

    const handlePointer = (e: MouseEvent | TouchEvent) => {
      const rect = canvas.getBoundingClientRect();
      const clientX = "touches" in e ? e.touches[0]?.clientX : e.clientX;
      const clientY = "touches" in e ? e.touches[0]?.clientY : e.clientY;
      if (clientX !== undefined && clientY !== undefined) {
        mouse.current = { x: clientX - rect.left, y: clientY - rect.top };
      }
    };
    const handleLeave = () => {
      mouse.current = { x: -1000, y: -1000 };
    };

    canvas.addEventListener("mousemove", handlePointer);
    canvas.addEventListener("touchmove", handlePointer, { passive: true });
    canvas.addEventListener("mouseleave", handleLeave);

    const rootStyles = getComputedStyle(document.documentElement);
    const primaryHSL = rootStyles.getPropertyValue("--primary").trim();

    // Spawn pulses periodically
    let spawnTimer = 0;

    let animId: number;

    const draw = () => {
      const w = canvas.width / dpr.current;
      const h = canvas.height / dpr.current;
      ctx.clearRect(0, 0, w, h);

      const mx = mouse.current.x;
      const my = mouse.current.y;
      const mouseActive = mx > -500;
      const mouseRadius = 200;

      const nodeArr = nodes.current;

      // Spawn new pulses
      spawnTimer++;
      if (spawnTimer % 8 === 0 && nodeArr.length > 0) {
        const startIdx = Math.floor(Math.random() * nodeArr.length);
        const startNode = nodeArr[startIdx];
        if (startNode.connections.length > 0) {
          const endIdx = startNode.connections[Math.floor(Math.random() * startNode.connections.length)];
          pulses.current.push({
            fromNode: startIdx,
            toNode: endIdx,
            progress: 0,
            speed: 0.015 + Math.random() * 0.02,
            alpha: 0.8,
          });
        }
      }

      // Mouse-triggered pulses
      if (mouseActive && spawnTimer % 4 === 0) {
        let closest = -1;
        let closestDist = Infinity;
        for (let i = 0; i < nodeArr.length; i++) {
          const dx = nodeArr[i].x - mx;
          const dy = nodeArr[i].y - my;
          const dist = Math.sqrt(dx * dx + dy * dy);
          if (dist < mouseRadius && dist < closestDist) {
            closestDist = dist;
            closest = i;
          }
        }
        if (closest >= 0 && nodeArr[closest].connections.length > 0) {
          const conns = nodeArr[closest].connections;
          const endIdx = conns[Math.floor(Math.random() * conns.length)];
          pulses.current.push({
            fromNode: closest,
            toNode: endIdx,
            progress: 0,
            speed: 0.03 + Math.random() * 0.03,
            alpha: 1,
          });
        }
      }

      // Decay node glow
      for (const n of nodeArr) {
        n.glow *= 0.95;
      }

      // Draw traces (circuit lines)
      const drawnEdges = new Set<string>();
      for (let i = 0; i < nodeArr.length; i++) {
        const n = nodeArr[i];
        for (const j of n.connections) {
          const edgeKey = i < j ? `${i}-${j}` : `${j}-${i}`;
          if (drawnEdges.has(edgeKey)) continue;
          drawnEdges.add(edgeKey);

          const m = nodeArr[j];

          // Calculate mouse proximity for brightness
          let traceAlpha = 0.06;
          if (mouseActive) {
            const midX = (n.x + m.x) / 2;
            const midY = (n.y + m.y) / 2;
            const dMouse = Math.sqrt((midX - mx) ** 2 + (midY - my) ** 2);
            if (dMouse < mouseRadius) {
              traceAlpha += (1 - dMouse / mouseRadius) * 0.2;
            }
          }

          // Draw right-angle circuit trace
          ctx.beginPath();
          // Alternate between horizontal-first and vertical-first
          if ((i + j) % 2 === 0) {
            ctx.moveTo(n.x, n.y);
            ctx.lineTo(m.x, n.y); // horizontal
            ctx.lineTo(m.x, m.y); // vertical
          } else {
            ctx.moveTo(n.x, n.y);
            ctx.lineTo(n.x, m.y); // vertical
            ctx.lineTo(m.x, m.y); // horizontal
          }
          ctx.strokeStyle = `hsl(${primaryHSL} / ${traceAlpha})`;
          ctx.lineWidth = 1;
          ctx.stroke();
        }
      }

      // Draw & update pulses
      pulses.current = pulses.current.filter((p) => p.progress <= 1 && p.alpha > 0.01);
      for (const p of pulses.current) {
        p.progress += p.speed;
        if (p.progress > 1) {
          // Chain to next connection
          const nextNode = nodeArr[p.toNode];
          if (nextNode.connections.length > 0 && Math.random() > 0.3) {
            const nextIdx = nextNode.connections[Math.floor(Math.random() * nextNode.connections.length)];
            pulses.current.push({
              fromNode: p.toNode,
              toNode: nextIdx,
              progress: 0,
              speed: p.speed,
              alpha: p.alpha * 0.7,
            });
          }
          nodeArr[p.toNode].glow = Math.min(nodeArr[p.toNode].glow + 0.5, 1);
          continue;
        }

        const from = nodeArr[p.fromNode];
        const to = nodeArr[p.toNode];
        const t = p.progress;

        // Calculate position along right-angle path
        let px: number, py: number;
        if ((p.fromNode + p.toNode) % 2 === 0) {
          if (t < 0.5) {
            px = from.x + (to.x - from.x) * (t * 2);
            py = from.y;
          } else {
            px = to.x;
            py = from.y + (to.y - from.y) * ((t - 0.5) * 2);
          }
        } else {
          if (t < 0.5) {
            px = from.x;
            py = from.y + (to.y - from.y) * (t * 2);
          } else {
            px = from.x + (to.x - from.x) * ((t - 0.5) * 2);
            py = to.y;
          }
        }

        // Pulse glow
        const grad = ctx.createRadialGradient(px, py, 0, px, py, 12);
        grad.addColorStop(0, `hsl(${primaryHSL} / ${p.alpha * 0.6})`);
        grad.addColorStop(1, `hsl(${primaryHSL} / 0)`);
        ctx.fillStyle = grad;
        ctx.fillRect(px - 12, py - 12, 24, 24);

        // Pulse dot
        ctx.beginPath();
        ctx.arc(px, py, 2.5, 0, Math.PI * 2);
        ctx.fillStyle = `hsl(${primaryHSL} / ${p.alpha})`;
        ctx.fill();
      }

      // Draw nodes
      for (let i = 0; i < nodeArr.length; i++) {
        const n = nodeArr[i];
        let nodeAlpha = 0.12;
        let nodeRadius = 2;

        // Mouse proximity glow
        if (mouseActive) {
          const dx = n.x - mx;
          const dy = n.y - my;
          const dist = Math.sqrt(dx * dx + dy * dy);
          if (dist < mouseRadius) {
            const proximity = 1 - dist / mouseRadius;
            nodeAlpha += proximity * 0.6;
            nodeRadius += proximity * 3;
            n.glow = Math.max(n.glow, proximity * 0.5);
          }
        }

        // Pulse glow effect
        nodeAlpha += n.glow * 0.5;
        nodeRadius += n.glow * 2;

        // Node glow halo
        if (n.glow > 0.1 || (mouseActive && nodeAlpha > 0.3)) {
          const grad = ctx.createRadialGradient(n.x, n.y, 0, n.x, n.y, nodeRadius * 4);
          grad.addColorStop(0, `hsl(${primaryHSL} / ${(nodeAlpha - 0.12) * 0.3})`);
          grad.addColorStop(1, `hsl(${primaryHSL} / 0)`);
          ctx.fillStyle = grad;
          ctx.fillRect(n.x - nodeRadius * 4, n.y - nodeRadius * 4, nodeRadius * 8, nodeRadius * 8);
        }

        // Node dot
        ctx.beginPath();
        ctx.arc(n.x, n.y, nodeRadius, 0, Math.PI * 2);
        ctx.fillStyle = `hsl(${primaryHSL} / ${Math.min(nodeAlpha, 0.9)})`;
        ctx.fill();

        // Square pad for junction nodes (3+ connections)
        if (n.connections.length >= 3) {
          ctx.strokeStyle = `hsl(${primaryHSL} / ${nodeAlpha * 0.5})`;
          ctx.lineWidth = 0.5;
          const s = nodeRadius + 2;
          ctx.strokeRect(n.x - s, n.y - s, s * 2, s * 2);
        }
      }

      // Mouse glow aura
      if (mouseActive) {
        const grad = ctx.createRadialGradient(mx, my, 0, mx, my, mouseRadius);
        grad.addColorStop(0, `hsl(${primaryHSL} / 0.08)`);
        grad.addColorStop(0.5, `hsl(${primaryHSL} / 0.02)`);
        grad.addColorStop(1, "transparent");
        ctx.fillStyle = grad;
        ctx.fillRect(mx - mouseRadius, my - mouseRadius, mouseRadius * 2, mouseRadius * 2);
      }

      animId = requestAnimationFrame(draw);
    };

    animId = requestAnimationFrame(draw);

    return () => {
      cancelAnimationFrame(animId);
      window.removeEventListener("resize", resize);
      canvas.removeEventListener("mousemove", handlePointer);
      canvas.removeEventListener("touchmove", handlePointer);
      canvas.removeEventListener("mouseleave", handleLeave);
    };
  }, [buildCircuit]);

  return (
    <canvas
      ref={canvasRef}
      className="absolute inset-0 w-full h-full z-[1]"
      style={{ touchAction: "none" }}
    />
  );
};

export default NeuralCanvas;
