import { onMount, onCleanup } from "solid-js";
import { cn } from "~/lib/utils";

interface ColorWaveBackgroundProps {
  class?: string;
  yOffset?: number;
  scale?: number;
  speed?: number;
}

const COLORS = {
  indigo: "#4f46e5",
  cyan: "#06b6d4",
  slate: "#0f172a",
};

export default function ColorWaveBackground(props: ColorWaveBackgroundProps) {
  const canvasRef = { current: null as HTMLCanvasElement | null };
  let animationId: number | undefined;

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

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

    const reducedMotion = window.matchMedia(
      "(prefers-reduced-motion: reduce)",
    ).matches;

    const resize = () => {
      const dpr = window.devicePixelRatio || 1;
      canvas.width = canvas.clientWidth * dpr;
      canvas.height = canvas.clientHeight * dpr;
      ctx.scale(dpr, dpr);
    };

    resize();
    window.addEventListener("resize", resize);

    const speed = props.speed ?? 1;
    const scale = props.scale ?? 1;
    const t0 = Date.now();

    const blobs = [
      {
        x: 0.2,
        y: 0.3,
        r: 0.35,
        color: COLORS.indigo,
        phase: 0,
      },
      {
        x: 0.7,
        y: 0.6,
        r: 0.4,
        color: COLORS.cyan,
        phase: 2.1,
      },
      {
        x: 0.5,
        y: 0.8,
        r: 0.3,
        color: COLORS.slate,
        phase: 4.2,
      },
    ];

    const draw = () => {
      const w = canvas.clientWidth;
      const h = canvas.clientHeight;
      const t = (Date.now() - t0) * 0.001 * speed;

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

      blobs.forEach((blob) => {
        const ox = Math.sin(t + blob.phase) * w * 0.15;
        const oy = Math.cos(t * 0.7 + blob.phase) * h * 0.12;
        const x = (blob.x + (props.yOffset ?? 0) * 0.001) * w + ox;
        const y = blob.y * h + oy;
        const r = blob.r * Math.min(w, h) * scale;

        const grad = ctx.createRadialGradient(x, y, 0, x, y, r);
        grad.addColorStop(0, blob.color + "40");
        grad.addColorStop(1, blob.color + "00");

        ctx.fillStyle = grad;
        ctx.beginPath();
        ctx.arc(x, y, r, 0, Math.PI * 2);
        ctx.fill();
      });

      if (!reducedMotion) {
        animationId = requestAnimationFrame(draw);
      }
    };

    draw();
  });

  onCleanup(() => {
    if (animationId !== undefined) {
      cancelAnimationFrame(animationId);
    }
  });

  const setRef = (el: HTMLCanvasElement) => {
    canvasRef.current = el;
  };

  return (
    <canvas
      ref={setRef}
      class={cn("absolute inset-0 w-full h-full", props.class)}
      style="pointer-events: none;"
    />
  );
}
