"use client";

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

interface Props {
  className?: string;
}

const GravityWave: React.FC<Props> = ({ className }) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);

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

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

    // Initialize dimensions based on parent container
    let width = canvas.width = canvas.parentElement?.clientWidth || window.innerWidth;
    let height = canvas.height = canvas.parentElement?.clientHeight || window.innerHeight;

    let animationFrameId: number;
    let time = 0;

    // Configuration
    const gap = 50; 
    const rows = Math.ceil(height / gap) + 4;
    const cols = Math.ceil(width / gap) + 4;
    
    // Mouse state
    const mouse = { x: -500, y: -500 };

    const handleResize = () => {
      // Resize based on parent element
      if (canvas.parentElement) {
        width = canvas.width = canvas.parentElement.clientWidth;
        height = canvas.height = canvas.parentElement.clientHeight;
      }
    };

    const handleMouseMove = (e: MouseEvent) => {
      const rect = canvas.getBoundingClientRect();
      mouse.x = e.clientX - rect.left;
      mouse.y = e.clientY - rect.top;
    };

    window.addEventListener("resize", handleResize);
    // Attach mouse move to the specific canvas/container, not window, if you want localized interaction
    // But keeping it on window usually feels smoother for "approaching" the section
    window.addEventListener("mousemove", handleMouseMove);

    const render = () => {
      ctx.clearRect(0, 0, width, height);
      time += 0.02;

      ctx.shadowBlur = 4;
      ctx.shadowColor = "rgba(34, 211, 238, 0.5)"; 
      
      const gradient = ctx.createLinearGradient(0, 0, width, height);
      gradient.addColorStop(0, "rgba(34, 211, 238, 0.4)"); 
      gradient.addColorStop(1, "rgba(52, 211, 153, 0.4)"); 
      
      ctx.strokeStyle = gradient;
      ctx.lineWidth = 1.5;

      // Re-calculate rows/cols in case of resize
      const currentRows = Math.ceil(height / gap) + 4;
      const currentCols = Math.ceil(width / gap) + 4;

      for (let iy = 0; iy < currentRows; iy++) {
        const yBase = iy * gap;
        ctx.beginPath();
        for (let ix = 0; ix < currentCols; ix++) {
          const xBase = ix * gap;

          const waveOffset = Math.sin(ix * 0.2 + time) * 8 + Math.cos(iy * 0.3 + time) * 8;
          const dx = xBase - mouse.x;
          const dy = yBase - mouse.y;
          const dist = Math.sqrt(dx * dx + dy * dy);
          
          const maxDist = 400; 
          let gravityX = 0;
          let gravityY = 0;

          if (dist < maxDist) {
            const force = (maxDist - dist) / maxDist;
            const power = force * 60; 
            const angle = Math.atan2(dy, dx);
            gravityX = Math.cos(angle) * power;
            gravityY = Math.sin(angle) * power;
          }

          const xFinal = xBase + gravityX;
          const yFinal = yBase + waveOffset + gravityY;

          if (ix === 0) ctx.moveTo(xFinal, yFinal);
          else ctx.lineTo(xFinal, yFinal);
        }
        ctx.stroke();
      }
      animationFrameId = requestAnimationFrame(render);
    };

    render();

    return () => {
      window.removeEventListener("resize", handleResize);
      window.removeEventListener("mousemove", handleMouseMove);
      cancelAnimationFrame(animationFrameId);
    };
  }, []);

  return (
    <canvas
      ref={canvasRef}
      className={`block w-full h-full ${className}`}
      style={{ touchAction: "none" }}
    />
  );
};

export default GravityWave;