"use client";

import React, {
  CSSProperties,
  useEffect,
  useLayoutEffect,
  useMemo,
  useRef,
} from "react";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";

type Axis = "x" | "y";

export type ParallaxImageProps = {
  src: string;
  alt?: string;
  amount?: number; // total translation across the scroll range (px)
  axis?: Axis; // default 'y'
  reverse?: boolean; // default true -> move up/left
  start?: string; // ScrollTrigger start
  end?: string; // ScrollTrigger end
  scrub?: boolean | number; // default true
  enabled?: boolean; // master on/off
  paused?: boolean; // pause without destroying
  disableBelow?: number; // disable under this width (px)
  className?: string;
  style?: CSSProperties;
  width?: number;
  height?: number;
  loading?: "eager" | "lazy";
  sizes?: string;
};

export default function ParallaxImage({
  src,
  alt = "",
  amount = 100,
  axis = "y",
  reverse = true,
  start = "top bottom",
  end = "bottom top",
  scrub = true,
  enabled = true,
  paused = false,
  disableBelow,
  className,
  style,
  width,
  height,
  loading,
  sizes,
}: ParallaxImageProps) {
  const imgRef = useRef<HTMLImageElement | null>(null);
  const tweenRef = useRef<gsap.core.Tween | null>(null);
  const stRef = useRef<ScrollTrigger | null>(null);

  const isBrowser = typeof window !== "undefined";

  const isActive = useMemo(() => {
    if (!enabled) return false;
    if (!isBrowser) return false;
    if (disableBelow && window.innerWidth < disableBelow) return false;
    return true;
  }, [enabled, disableBelow, isBrowser]);

  useLayoutEffect(() => {
    if (!isBrowser) return;

    // cleanup previous
    if (tweenRef.current) {
      tweenRef.current.kill();
      tweenRef.current = null;
    }
    if (stRef.current) {
      stRef.current.kill();
      stRef.current = null;
    }

    const el = imgRef.current;
    if (!el) return;

    // Reset when inactive
    if (!isActive) {
      gsap.set(el, { x: 0, y: 0, force3D: true, z: 0 });
      return;
    }

    const half = amount / 2;
    const fromVal = reverse ? half : -half;
    const toVal = reverse ? -half : half;

    const fromProps: gsap.TweenVars = { force3D: true };
    const toProps: gsap.TweenVars = {
      ease: "none",
      force3D: true,
      autoRound: false,
    };

    if (axis === "y") {
      fromProps.y = fromVal;
      toProps.y = toVal;
    } else {
      fromProps.x = fromVal;
      toProps.x = toVal;
    }

    tweenRef.current = gsap.fromTo(el, fromProps, {
      ...toProps,
      scrollTrigger: {
        trigger: el,
        start,
        end,
        scrub,
        invalidateOnRefresh: true,
      },
    });

    stRef.current = tweenRef.current.scrollTrigger ?? null;

    return () => {
      if (tweenRef.current) {
        tweenRef.current.kill();
        tweenRef.current = null;
      }
      if (stRef.current) {
        stRef.current.kill();
        stRef.current = null;
      }
    };
  }, [isActive, amount, axis, start, end, scrub, reverse, isBrowser]);

  // Pause/resume
  useEffect(() => {
    const st = stRef.current;
    if (!st) return;
    if (paused) {
      st.disable();
    } else {
      st.enable();
      st.refresh();
    }
  }, [paused]);

  // Rebuild on resize if using disableBelow
  useEffect(() => {
    if (!isBrowser || !disableBelow) return;
    const onResize = () => ScrollTrigger.refresh();
    window.addEventListener("resize", onResize);
    return () => window.removeEventListener("resize", onResize);
  }, [isBrowser, disableBelow]);

  return (
    // eslint-disable-next-line @next/next/no-img-element
    <img
      ref={imgRef}
      src={src}
      alt={alt}
      className={className}
      style={{
        willChange: "transform",
        backfaceVisibility: "hidden",
        objectFit: "cover",
        width: "100%",
        height: "100%",
        ...(style || {}),
      }}
      width={width}
      height={height}
      loading={loading}
      sizes={sizes}
    />
  );
}
