import { useState, useEffect, useRef } from "react";
import Title from "@/components/Title";
import styles from "./styles.module.scss";
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
import Button from "../../components/Button";
import { images } from "../../data";
import WheelPathHeader from "../../components/WheelPathHeader";
import routes from "@/routes";
import { useNavigate } from "react-router-dom";
import { DotLottieReact } from "@lottiefiles/dotlottie-react";
import { useLottie } from "@/hooks/lottie/useLottie";
import { ELottieKeys } from "@/hooks/lottie/useLottie";
import { EUnleashFlags, useUnleash } from "@/hooks/ab/unleash/useUnleash";
import Loader, { LoaderColor } from "@/components/Loader";

type WheelState =
  | "spinning"
  | "stopping"
  | "stopped"
  | "accelerating"
  | "ready-for-second-spin";

function WheelOfFortune() {
  const { translate } = useTranslations(ELocalesPlacement.CompatibilityV2);
  const navigate = useNavigate();
  const { animationData: animationDataConfetti } = useLottie({
    loadKey: ELottieKeys.confetti,
  });

  const [wheelState, setWheelState] = useState<WheelState>("spinning");
  const wheelStateRef = useRef<WheelState>("spinning");
  const [showSkipButton, setShowSkipButton] = useState(true);
  const [showMainButton, setShowMainButton] = useState(true);
  const [isConfettiVisible, setIsConfettiVisible] = useState(false);

  const { isReady, variant: v2CompatibilityTrialChoicePath } = useUnleash({
    flag: EUnleashFlags.v2CompatibilityTrialChoicePath,
  });

  const updateWheelState = (newState: WheelState) => {
    wheelStateRef.current = newState;
    setWheelState(newState);
  };
  const [currentRotation, setCurrentRotation] = useState(0);
  const [isButtonDisabled, setIsButtonDisabled] = useState(false);
  const wheelRef = useRef<HTMLImageElement>(null);
  const animationRef = useRef<number>();

  const WHEEL_SPEED = 760;
  const ACCELERATION_DURATION = 2000;
  const STOP_DURATION = 3000;

  const FIRST_STOP_ANGLE = 240;
  const SECOND_STOP_ANGLE = 274;

  useEffect(() => {
    if (wheelState === "spinning" && currentRotation === 0) {
      startSpinning();
    }

    return () => {
      if (animationRef.current) {
        cancelAnimationFrame(animationRef.current);
      }
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const startSpinning = () => {
    setIsButtonDisabled(false);

    accelerateWheel();
  };

  const accelerateWheel = () => {
    let startTime: number;
    let lastTime: number;

    const animate = (timestamp: number) => {
      if (!startTime) {
        startTime = timestamp;
        lastTime = timestamp;
      }

      const elapsed = timestamp - startTime;
      const deltaTime = timestamp - lastTime;
      lastTime = timestamp;

      const progress = Math.min(elapsed / ACCELERATION_DURATION, 1);

      const easedProgress = 1 - Math.pow(1 - progress, 3);
      const currentSpeed = WHEEL_SPEED * easedProgress;

      const rotationIncrement = (currentSpeed * deltaTime) / 1000;
      setCurrentRotation((prev) => prev + rotationIncrement);

      if (progress < 1) {
        animationRef.current = requestAnimationFrame(animate);
      } else {
        startContinuousSpinning();
      }
    };

    animationRef.current = requestAnimationFrame(animate);
  };

  const startContinuousSpinning = () => {
    let lastTime: number;

    const animate = (timestamp: number) => {
      if (!lastTime) lastTime = timestamp;

      const deltaTime = timestamp - lastTime;
      lastTime = timestamp;

      const rotationIncrement = (WHEEL_SPEED * deltaTime) / 1000;
      setCurrentRotation((prev) => prev + rotationIncrement);

      if (
        wheelStateRef.current === "spinning" ||
        wheelStateRef.current === "ready-for-second-spin"
      ) {
        animationRef.current = requestAnimationFrame(animate);
      }
    };

    animationRef.current = requestAnimationFrame(animate);
  };

  const stopWheel = () => {
    if (isButtonDisabled || wheelState === "stopping") return;

    setIsButtonDisabled(true);
    updateWheelState("stopping");

    if (animationRef.current) {
      cancelAnimationFrame(animationRef.current);
    }

    const originalState = wheelState;
    const targetAngle =
      originalState === "spinning" ? FIRST_STOP_ANGLE : SECOND_STOP_ANGLE;

    if (originalState === "ready-for-second-spin") {
      setShowMainButton(false);
    }

    const currentAngle = currentRotation % 360;
    const additionalRotations =
      Math.ceil((currentAngle + 360 - targetAngle) / 360) * 360;
    const finalRotation =
      currentRotation + additionalRotations - (currentAngle - targetAngle);

    let startTime: number;
    const startRotation = currentRotation;

    const animate = (timestamp: number) => {
      if (!startTime) startTime = timestamp;
      const elapsed = timestamp - startTime;
      const progress = Math.min(elapsed / STOP_DURATION, 1);

      const easedProgress = 1 - Math.pow(1 - progress, 4);
      const currentRotation =
        startRotation + (finalRotation - startRotation) * easedProgress;

      setCurrentRotation(currentRotation);

      if (progress < 1) {
        animationRef.current = requestAnimationFrame(animate);
      } else {
        updateWheelState("stopped");
        setIsButtonDisabled(false);

        if (originalState === "ready-for-second-spin") {
          setIsConfettiVisible(true);

          setTimeout(() => {
            handleNext();
          }, 5000);
        }
      }
    };

    animationRef.current = requestAnimationFrame(animate);
  };

  const handleButtonClick = () => {
    if (wheelState === "spinning" || wheelState === "ready-for-second-spin") {
      stopWheel();
    } else if (wheelState === "stopped") {
      updateWheelState("ready-for-second-spin");
      setShowSkipButton(false);
      setIsButtonDisabled(false);
      accelerateWheel();
    }
  };

  const getButtonText = () => {
    switch (wheelState) {
      case "spinning":
      case "ready-for-second-spin":
        return translate("/wheel-of-fortune.button_stop");
      case "stopped":
        return translate("/wheel-of-fortune.button_last_chance");
      case "accelerating":
        return translate("/wheel-of-fortune.button_stop");
      default:
        return translate("/wheel-of-fortune.button_stop");
    }
  };

  const getWheelClassName = () => {
    const baseClass = styles.wheelImage;
    if (
      wheelState === "spinning" ||
      wheelState === "accelerating" ||
      wheelState === "ready-for-second-spin"
    ) {
      return `${baseClass} ${styles.spinning} ${v2CompatibilityTrialChoicePath !== "v3" && styles.blurSpinning}`;
    }
    if (wheelState === "stopping") {
      return `${baseClass} ${styles.stopping} ${v2CompatibilityTrialChoicePath !== "v3" && styles.blurStopping}`;
    }
    return baseClass;
  };

  const handleNext = () => {
    navigate(routes.client.compatibilityV2SpecialOffer());
  };

  if (!isReady) {
    return <Loader color={LoaderColor.Black} />;
  }

  return (
    <div className={styles.container}>
      <WheelPathHeader />

      <Title variant="h1" className={styles.title}>
        {translate("/wheel-of-fortune.title")}
      </Title>

      <p className={styles.description}>
        {translate("/wheel-of-fortune.description")}
      </p>

      <div className={styles.wheelContainer}>
        <img
          ref={wheelRef}
          className={getWheelClassName()}
          src={images("wheel-of-fortune/wheel.png")}
          alt="Wheel of Fortune"
          style={{
            transform: `rotate(${currentRotation}deg)`,
          }}
        />
        <svg
          width="30"
          height="30"
          viewBox="0 0 30 30"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
          className={styles.giftImage}
        >
          <path
            d="M11.1621 4.03125L13.2012 7.5H13.125H8.90625C7.61133 7.5 6.5625 6.45117 6.5625 5.15625C6.5625 3.86133 7.61133 2.8125 8.90625 2.8125H9.03516C9.9082 2.8125 10.7227 3.27539 11.1621 4.03125ZM3.75 5.15625C3.75 6 3.95508 6.79688 4.3125 7.5H1.875C0.837891 7.5 0 8.33789 0 9.375V13.125C0 14.1621 0.837891 15 1.875 15H28.125C29.1621 15 30 14.1621 30 13.125V9.375C30 8.33789 29.1621 7.5 28.125 7.5H25.6875C26.0449 6.79688 26.25 6 26.25 5.15625C26.25 2.30859 23.9414 0 21.0938 0H20.9648C19.0957 0 17.3613 0.990234 16.4121 2.60156L15 5.00977L13.5879 2.60742C12.6387 0.990234 10.9043 0 9.03516 0H8.90625C6.05859 0 3.75 2.30859 3.75 5.15625ZM23.4375 5.15625C23.4375 6.45117 22.3887 7.5 21.0938 7.5H16.875H16.7988L18.8379 4.03125C19.2832 3.27539 20.0918 2.8125 20.9648 2.8125H21.0938C22.3887 2.8125 23.4375 3.86133 23.4375 5.15625ZM1.875 16.875V27.1875C1.875 28.7402 3.13477 30 4.6875 30H13.125V16.875H1.875ZM16.875 30H25.3125C26.8652 30 28.125 28.7402 28.125 27.1875V16.875H16.875V30Z"
            fill="#FF8004"
          />
        </svg>
        <svg
          width="81"
          height="76"
          viewBox="0 0 81 76"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
          className={styles.cursor}
        >
          <g filter="url(#filter0_d_698_4287)">
            <path
              d="M43.0981 57.25C41.9434 59.25 39.0566 59.25 37.9019 57.25L17.5503 22C16.3956 20 17.839 17.5 20.1484 17.5L60.8516 17.5C63.161 17.5 64.6044 20 63.4497 22L43.0981 57.25Z"
              fill="#FF0D11"
            />
            <path
              d="M43.9639 57.75C42.4242 60.4165 38.5758 60.4165 37.0361 57.75L16.6846 22.5C15.145 19.8333 17.0692 16.5 20.1484 16.5L60.8516 16.5C63.9308 16.5 65.855 19.8333 64.3154 22.5L43.9639 57.75Z"
              stroke="white"
              strokeWidth="2"
            />
          </g>
          <defs>
            <filter
              id="filter0_d_698_4287"
              x="0.141113"
              y="0.5"
              width="80.7178"
              height="75.25"
              filterUnits="userSpaceOnUse"
              colorInterpolationFilters="sRGB"
            >
              <feFlood floodOpacity="0" result="BackgroundImageFix" />
              <feColorMatrix
                in="SourceAlpha"
                type="matrix"
                values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
                result="hardAlpha"
              />
              <feOffset />
              <feGaussianBlur stdDeviation="7.5" />
              <feComposite in2="hardAlpha" operator="out" />
              <feColorMatrix
                type="matrix"
                values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.4 0"
              />
              <feBlend
                mode="normal"
                in2="BackgroundImageFix"
                result="effect1_dropShadow_698_4287"
              />
              <feBlend
                mode="normal"
                in="SourceGraphic"
                in2="effect1_dropShadow_698_4287"
                result="shape"
              />
            </filter>
          </defs>
        </svg>
      </div>

      {showMainButton && (
        <Button
          className={styles.button}
          onClick={handleButtonClick}
          disabled={isButtonDisabled}
        >
          {getButtonText()}
        </Button>
      )}

      {showSkipButton && (
        <Button className={styles.skipButton} onClick={handleNext}>
          {translate("/wheel-of-fortune.skip_button")}
        </Button>
      )}

      {isConfettiVisible && (
        <div className={styles["lottie-animation-container-confetti"]}>
          {animationDataConfetti && (
            <DotLottieReact
              className={`${styles["lottie-animation-confetti"]} ym-hide-content`}
              data={animationDataConfetti}
              autoplay
              width={80}
            />
          )}
        </div>
      )}
    </div>
  );
}

export default WheelOfFortune;
