"use client";

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

interface Node {
  x: number;
  y: number;
  baseX: number;
  baseY: number;
  vx: number;
  vy: number;
  isHub: boolean;
  pulsePhase: number;
  radius: number;
}

interface Pulse {
  edgeIdx: number;
  progress: number;
  speed: number;
  direction: 1 | -1;
}

const NODE_COUNT = 80;
const MAX_EDGE_DIST = 180;
const MOUSE_RADIUS = 250;
const MOUSE_REPEL = 0.3;
const DRIFT_SPEED = 0.15;
const RETURN_FORCE = 0.005;

function createNodes(w: number, h: number): Node[] {
  const nodes: Node[] = [];
  for (let i = 0; i < NODE_COUNT; i++) {
    const x = Math.random() * w;
    const y = Math.random() * h;
    nodes.push({
      x,
      y,
      baseX: x,
      baseY: y,
      vx: (Math.random() - 0.5) * DRIFT_SPEED,
      vy: (Math.random() - 0.5) * DRIFT_SPEED,
      isHub: i < 12,
      pulsePhase: Math.random() * Math.PI * 2,
      radius: i < 12 ? 2.5 : 1.2,
    });
  }
  return nodes;
}

function buildEdges(nodes: Node[]): [number, number][] {
  const edges: [number, number][] = [];
  for (let i = 0; i < nodes.length; i++) {
    for (let j = i + 1; j < nodes.length; j++) {
      const dx = nodes[i].x - nodes[j].x;
      const dy = nodes[i].y - nodes[j].y;
      if (dx * dx + dy * dy < MAX_EDGE_DIST * MAX_EDGE_DIST) {
        edges.push([i, j]);
      }
    }
  }
  return edges;
}

export function Background() {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const nodesRef = useRef<Node[]>([]);
  const pulsesRef = useRef<Pulse[]>([]);
  const mouseRef = useRef({ x: -1000, y: -1000 });
  const frameRef = useRef<number>(0);
  const timeRef = useRef(0);

  const spawnPulse = useCallback((edges: [number, number][]) => {
    if (edges.length === 0) return;
    const idx = Math.floor(Math.random() * edges.length);
    pulsesRef.current.push({
      edgeIdx: idx,
      progress: 0,
      speed: 0.008 + Math.random() * 0.012,
      direction: Math.random() > 0.5 ? 1 : -1,
    });
  }, []);

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

    let w = window.innerWidth;
    let h = window.innerHeight;
    canvas.width = w;
    canvas.height = h;

    nodesRef.current = createNodes(w, h);
    pulsesRef.current = [];

    const handleResize = () => {
      w = window.innerWidth;
      h = window.innerHeight;
      canvas.width = w;
      canvas.height = h;
      nodesRef.current = createNodes(w, h);
      pulsesRef.current = [];
    };

    const handleMouseMove = (e: MouseEvent) => {
      mouseRef.current = { x: e.clientX, y: e.clientY };
    };

    const handleMouseLeave = () => {
      mouseRef.current = { x: -1000, y: -1000 };
    };

    window.addEventListener("resize", handleResize);
    window.addEventListener("mousemove", handleMouseMove);
    document.addEventListener("mouseleave", handleMouseLeave);

    const animate = () => {
      timeRef.current += 1;
      const nodes = nodesRef.current;
      const mx = mouseRef.current.x;
      const my = mouseRef.current.y;

      ctx.clearRect(0, 0, w, h);

      // Update node positions
      for (const node of nodes) {
        // Drift
        node.x += node.vx;
        node.y += node.vy;

        // Return to base
        node.vx += (node.baseX - node.x) * RETURN_FORCE;
        node.vy += (node.baseY - node.y) * RETURN_FORCE;

        // Damping
        node.vx *= 0.99;
        node.vy *= 0.99;

        // Mouse interaction — repel
        const dmx = node.x - mx;
        const dmy = node.y - my;
        const distMouse = Math.sqrt(dmx * dmx + dmy * dmy);
        if (distMouse < MOUSE_RADIUS && distMouse > 0) {
          const force = (1 - distMouse / MOUSE_RADIUS) * MOUSE_REPEL;
          node.vx += (dmx / distMouse) * force;
          node.vy += (dmy / distMouse) * force;
        }

        // Boundary wrap
        if (node.x < -20) node.x = w + 20;
        if (node.x > w + 20) node.x = -20;
        if (node.y < -20) node.y = h + 20;
        if (node.y > h + 20) node.y = -20;
      }

      // Build edges dynamically
      const edges = buildEdges(nodes);

      // Draw edges
      for (let i = 0; i < edges.length; i++) {
        const [a, b] = edges[i];
        const dx = nodes[a].x - nodes[b].x;
        const dy = nodes[a].y - nodes[b].y;
        const dist = Math.sqrt(dx * dx + dy * dy);
        const alpha = (1 - dist / MAX_EDGE_DIST) * 0.12;

        // Brighter edges near mouse
        const edgeMx = (nodes[a].x + nodes[b].x) / 2;
        const edgeMy = (nodes[a].y + nodes[b].y) / 2;
        const edgeMouseDist = Math.sqrt(
          (edgeMx - mx) ** 2 + (edgeMy - my) ** 2
        );
        const mouseBoost =
          edgeMouseDist < MOUSE_RADIUS
            ? (1 - edgeMouseDist / MOUSE_RADIUS) * 0.2
            : 0;

        ctx.beginPath();
        ctx.moveTo(nodes[a].x, nodes[a].y);
        ctx.lineTo(nodes[b].x, nodes[b].y);
        ctx.strokeStyle = `rgba(192, 119, 144, ${alpha + mouseBoost})`;
        ctx.lineWidth = 0.5;
        ctx.stroke();
      }

      // Spawn pulses
      if (timeRef.current % 8 === 0) {
        spawnPulse(edges);
      }

      // Draw & update pulses
      const activePulses: Pulse[] = [];
      for (const pulse of pulsesRef.current) {
        pulse.progress += pulse.speed;
        if (pulse.progress > 1) {
          // Chain reaction — sometimes spawn a new pulse from the destination node
          if (Math.random() < 0.4 && pulse.edgeIdx < edges.length) {
            const destNode =
              pulse.direction === 1
                ? edges[pulse.edgeIdx][1]
                : edges[pulse.edgeIdx][0];
            // Find connected edges from destination
            const connected = edges
              .map((e, idx) => ({ e, idx }))
              .filter(
                ({ e, idx }) =>
                  idx !== pulse.edgeIdx &&
                  (e[0] === destNode || e[1] === destNode)
              );
            if (connected.length > 0) {
              const next =
                connected[Math.floor(Math.random() * connected.length)];
              activePulses.push({
                edgeIdx: next.idx,
                progress: 0,
                speed: 0.01 + Math.random() * 0.01,
                direction:
                  next.e[0] === destNode ? 1 : -1,
              });
            }
          }
          continue;
        }

        if (pulse.edgeIdx >= edges.length) continue;

        const [a, b] = edges[pulse.edgeIdx];
        const na = nodes[a];
        const nb = nodes[b];
        const t = pulse.direction === 1 ? pulse.progress : 1 - pulse.progress;
        const px = na.x + (nb.x - na.x) * t;
        const py = na.y + (nb.y - na.y) * t;

        // Pulse head glow
        const gradient = ctx.createRadialGradient(px, py, 0, px, py, 12);
        gradient.addColorStop(0, "rgba(192, 119, 144, 0.6)");
        gradient.addColorStop(0.5, "rgba(192, 119, 144, 0.15)");
        gradient.addColorStop(1, "rgba(192, 119, 144, 0)");
        ctx.beginPath();
        ctx.arc(px, py, 12, 0, Math.PI * 2);
        ctx.fillStyle = gradient;
        ctx.fill();

        // Bright core
        ctx.beginPath();
        ctx.arc(px, py, 2, 0, Math.PI * 2);
        ctx.fillStyle = "rgba(219, 168, 184, 0.8)";
        ctx.fill();

        // Trail
        const trailLen = 0.15;
        const tStart = Math.max(0, t - trailLen);
        const sx = na.x + (nb.x - na.x) * tStart;
        const sy = na.y + (nb.y - na.y) * tStart;
        const trailGrad = ctx.createLinearGradient(sx, sy, px, py);
        trailGrad.addColorStop(0, "rgba(192, 119, 144, 0)");
        trailGrad.addColorStop(1, "rgba(192, 119, 144, 0.3)");
        ctx.beginPath();
        ctx.moveTo(sx, sy);
        ctx.lineTo(px, py);
        ctx.strokeStyle = trailGrad;
        ctx.lineWidth = 1.5;
        ctx.stroke();

        activePulses.push(pulse);
      }
      pulsesRef.current = activePulses;

      // Draw nodes
      for (const node of nodes) {
        const pulse =
          Math.sin(timeRef.current * 0.03 + node.pulsePhase) * 0.5 + 0.5;

        // Mouse proximity glow
        const dMouse = Math.sqrt(
          (node.x - mx) ** 2 + (node.y - my) ** 2
        );
        const mouseGlow =
          dMouse < MOUSE_RADIUS ? (1 - dMouse / MOUSE_RADIUS) : 0;

        if (node.isHub) {
          // Hub outer glow
          const glowR = node.radius * (3 + pulse * 2) + mouseGlow * 8;
          const glowAlpha = 0.06 + pulse * 0.04 + mouseGlow * 0.1;
          const gradient = ctx.createRadialGradient(
            node.x, node.y, 0,
            node.x, node.y, glowR
          );
          gradient.addColorStop(0, `rgba(192, 119, 144, ${glowAlpha})`);
          gradient.addColorStop(1, "rgba(192, 119, 144, 0)");
          ctx.beginPath();
          ctx.arc(node.x, node.y, glowR, 0, Math.PI * 2);
          ctx.fillStyle = gradient;
          ctx.fill();

          // Hub core
          ctx.beginPath();
          ctx.arc(node.x, node.y, node.radius, 0, Math.PI * 2);
          ctx.fillStyle = `rgba(192, 119, 144, ${0.4 + pulse * 0.2 + mouseGlow * 0.3})`;
          ctx.fill();
        } else {
          ctx.beginPath();
          ctx.arc(node.x, node.y, node.radius + mouseGlow * 1.5, 0, Math.PI * 2);
          ctx.fillStyle = `rgba(120, 113, 108, ${0.15 + mouseGlow * 0.4})`;
          ctx.fill();
        }
      }

      frameRef.current = requestAnimationFrame(animate);
    };

    frameRef.current = requestAnimationFrame(animate);

    return () => {
      cancelAnimationFrame(frameRef.current);
      window.removeEventListener("resize", handleResize);
      window.removeEventListener("mousemove", handleMouseMove);
      document.removeEventListener("mouseleave", handleMouseLeave);
    };
  }, [spawnPulse]);

  return (
    <div className="pointer-events-none fixed inset-0 z-0 overflow-hidden">
      <canvas ref={canvasRef} className="absolute inset-0 h-full w-full" />

      {/* Primary glow — top center */}
      <div
        className="absolute -top-[20%] left-1/2 h-[800px] w-[800px] -translate-x-1/2 rounded-full"
        style={{
          background:
            "radial-gradient(circle, rgba(122,59,78,0.15) 0%, rgba(122,59,78,0.05) 40%, transparent 70%)",
        }}
      />

      {/* Accent glow — bottom right */}
      <div
        className="absolute -bottom-[10%] -right-[10%] h-[600px] w-[600px] rounded-full"
        style={{
          background:
            "radial-gradient(circle, rgba(194,112,62,0.08) 0%, rgba(194,112,62,0.03) 40%, transparent 70%)",
        }}
      />

      {/* Secondary glow — left */}
      <div
        className="absolute top-[40%] -left-[10%] h-[500px] w-[500px] rounded-full"
        style={{
          background:
            "radial-gradient(circle, rgba(74,107,130,0.06) 0%, transparent 60%)",
        }}
      />
    </div>
  );
}
