import { type ComponentType, useEffect, useRef, useState } from "react";
import { motion, type SVGMotionProps, useAnimationControls } from "motion/react";
import clsx, { type ClassValue } from "clsx";

import Bee1 from "./bees/Bee1";
import Bee2 from "./bees/Bee2";
import Bee3 from "./bees/Bee3";
import Bee4 from "./bees/Bee4";
import Bee5 from "./bees/Bee5";
import Bee6 from "./bees/Bee6";

const RANGE = 70;
const MIN_DURATION = 0.1;
const MAX_DURATION = 0.15;

function AnimatedBee({ Bee }: { Bee: ComponentType }) {
  const moveControls = useAnimationControls();
  const [facingLeft, setFacingLeft] = useState(false);
  const lastX = useRef(0);

  useEffect(() => {
    let active = true;

    async function fly() {
      while (active) {
        const nextX = (Math.random() - 0.5) * RANGE * 2;
        const nextY = (Math.random() - 0.5) * RANGE * 2;
        setFacingLeft(nextX < lastX.current);
        lastX.current = nextX;

        const duration = MIN_DURATION + Math.random() * (MAX_DURATION - MIN_DURATION);
        await moveControls.start({
          x: nextX,
          y: nextY,
          rotate: (Math.random() - 0.5) * 30,
          transition: {
            duration,
            x: { duration, ease: [Math.random(), Math.random(), Math.random(), Math.random()] },
            y: { duration, ease: [Math.random(), Math.random(), Math.random(), Math.random()] },
            rotate: { duration, ease: "linear" },
          },
        });
      }
    }

    const timeout = setTimeout(fly, Math.random() * 500);
    return () => {
      active = false;
      clearTimeout(timeout);
    };
  }, [moveControls]);

  return (
    <motion.g animate={moveControls}>
      <g
        style={{
          transformBox: "fill-box",
          transformOrigin: "center",
          transform: facingLeft ? "scaleX(1)" : "scaleX(-1)",
        }}
      >
        <Bee />
      </g>
    </motion.g>
  );
}

const Bees = [Bee1, Bee2, Bee3, Bee4, Bee5, Bee6];

type Props = Omit<SVGMotionProps<SVGElement>, "className"> & {
  className?: ClassValue;
  count?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
};

export default function MovingBees({ className, count = 6, ...props }: Props) {
  return (
    <motion.svg
      {...props}
      className={clsx(className)}
      viewBox="0 0 189 174"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
      overflow="visible"
    >
      {Bees.slice(0, count).map((Bee, i) => (
        <AnimatedBee key={i} Bee={Bee} />
      ))}
    </motion.svg>
  );
}
