'use client'

import { useThemeEvents } from '@/hooks/theme-events';
import { getEvent } from '@/lib/utils';
import clsx from 'clsx';
import NextImage from 'next/image';
import { ReactNode, useEffect, useRef, useState } from 'react';

interface Snowflake {
  x: number;
  y: number;
  radius: number;
  speed: number;
  sway: number;
  swayOffset: number;
  opacity: number;
  rotation: number;
  rotationSpeed: number;
}

interface ChristmasProps {
  left: number;
  top: number;
  size: number;
  img: string;
  className?: string;
  flip?: boolean;
  absolute?: boolean;
}

export const ChristmasExclusive = ({ children }: { children: ReactNode }) => {
  const eventNow = useThemeEvents()?.event;

  if (eventNow?.name == 'christmas') return children;
  return null;
}

export const ChristmasProperty: React.FC<ChristmasProps> = ({
  left,
  top,
  img,
  size,
  className,
  flip
}) => {
  return (
    <ChristmasExclusive>
      <div
        className={clsx('absolute md:block hidden', flip && '-scale-x-100', className)}
        style={{
          left, top
        }}
      >
        <NextImage
          className='pointer-events-none'
          src={img}
          alt='Christmas prop'
          height={size}
          width={size}
          unoptimized={img.slice(img.length - 3, img.length) == 'gif'}
        />
      </div>
    </ChristmasExclusive>
  )
}

function SnowfallRawBackground() {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
  const snowflakesRef = useRef<Snowflake[]>([]);
  const animationFrameRef = useRef<number>(0);
  const imageRef = useRef<HTMLImageElement | null>(null);

  useEffect(() => {
    const updateDimensions = () => {
      setDimensions({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    };

    updateDimensions();
    window.addEventListener('resize', updateDimensions);
    
    return () => window.removeEventListener('resize', updateDimensions);
  }, []);

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

    canvas.width = dimensions.width;
    canvas.height = dimensions.height;

    // Load the snowflake image using a plain Image so we can draw it to canvas reliably
    const img = new Image();
    img.src = '/images/event_snowflake.png';
    let mounted = true;

    const start = () => {
      if (!mounted) return;
      imageRef.current = img;

      const createSnowflake = (init?: boolean): Snowflake => {
        let posy = -10;
        let radius = Math.random() * 18 + 10;
        let speed = Math.random() * 1 + 0.5;
        let sway = Math.random() * 0.5 + 0.2;

        if (init) {
          const initHeight = (dimensions.height / 1.1);
          posy = Math.random() * initHeight + posy;
          radius = (posy / (initHeight + posy) - 1) * -radius;
        }

        if (window.innerWidth < 768) {
          radius /= 1.4;
        }

        return {
          x: Math.random() * dimensions.width,
          y: posy,
          radius,
          speed,
          sway,
          swayOffset: Math.random() * Math.PI * 2,
          opacity: Math.random() * 0.5 + 0.2,
          rotation: Math.random() * Math.PI * 2,
          rotationSpeed: (Math.random() - 0.5) * 0.02,
        }
      };

      const snowflakes: Snowflake[] = [];
      for (let i = 0; i < 80; i++) {
        snowflakes.push(createSnowflake(true));
      }
      snowflakesRef.current = snowflakes;

      const animate = () => {
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        snowflakesRef.current.forEach((flake, index) => {
          flake.y += flake.speed;
          flake.x += Math.sin(flake.swayOffset + flake.y * 0.02) * flake.sway;
          flake.rotation += flake.rotationSpeed;

          const shrink = dimensions.height < 768 ? 0.005 : 0.01;
          flake.radius = Math.max(2, flake.radius - shrink);

          if (flake.y > dimensions.height || flake.radius <= 0.5) {
            snowflakesRef.current[index] = createSnowflake();
            return;
          }

          ctx.save();
          ctx.globalAlpha = flake.opacity;
          ctx.translate(flake.x, flake.y);
          ctx.rotate(flake.rotation);

          ctx.drawImage(
            img,
            -flake.radius / 2,
            -flake.radius / 2,
            flake.radius,
            flake.radius
          );

          ctx.restore();
        });

        animationFrameRef.current = requestAnimationFrame(animate);
      };

      animationFrameRef.current = requestAnimationFrame(animate);
    };

    if (img.complete) start();
    else img.onload = start;

    return () => {
      mounted = false;
      cancelAnimationFrame(animationFrameRef.current);
      img.onload = null;
      imageRef.current = null;
    };
  }, [dimensions]);

  return (
    <canvas
      ref={canvasRef}
      className="fixed top-0 left-0 w-full h-full pointer-events-none"
      style={{ zIndex: 0 }}
      aria-hidden="true"
    />
  );
}

export const SnowfallBackground = () => (
  <ChristmasExclusive>
    <SnowfallRawBackground />
  </ChristmasExclusive>
)
