import React, {
    useEffect,
    useRef,
} from 'react';

export type TiltAxis = 'both' | 'horizontal' | 'vertical';

type FullscreenTiltBackdropProps = {
    imageUrl: string;
    /** максимальный наклон по каждой оси, в градусах */
    maxTiltDeg?: number;         // default 12
    /** ось наклона: horizontal — только ry (влево/вправо), vertical — только rx (вверх/вниз), both — обе оси */
    tiltAxis?: TiltAxis;         // default 'both'
    /** перспектива в px */
    perspective?: number;        // default 1000
    /** доп. масштаб при ховере (легкая «дыхалка») */
    hoverScale?: number;         // default 1.02
    /** скорость сглаживания (0..1) */
    ease?: number;               // default 0.12
    /** запас к оверскейлу на всякий случай */
    safetyMargin?: number;       // default 0.04 (4%)
    /** тень / фильтр на вкус */
    filterCss?: string;          // optional
};

const Tilt3DImage: React.FC<FullscreenTiltBackdropProps> = ({
    imageUrl,
    maxTiltDeg = 10,
    tiltAxis = 'both',
    perspective = 1000,
    hoverScale = 1.02,
    ease = 0.12,
    safetyMargin = 0.3,
    filterCss,
}) => {
    const planeRef = useRef<HTMLDivElement | null>(null);
    const isHoverRef = useRef(false);
    const rafRef = useRef<number | null>(null);
    const targetRef = useRef({ rx: 0, ry: 0, scale: 1 });
    const currentRef = useRef({ rx: 0, ry: 0, scale: 1 });
    const baseScaleRef = useRef(1);

    // оценка нужного оверскейла, чтобы не было «пустых» зон
    // При наклоне плоскость проецируется и визуально «сжимается» ~ по cos(θ).
    const computeBaseScale = (deg: number, margin: number, axis: TiltAxis) => {
        const rad = (deg * Math.PI) / 180;
        const cos = Math.cos(rad);
        const scale = axis === 'both' ? 1 / (cos * cos) : 1 / cos;
        return scale * (1 + margin);
    };

    // Пересчитать базовый масштаб при монтировании/резайзе
    useEffect(() => {
        const recalc = () => {
            baseScaleRef.current = computeBaseScale(maxTiltDeg, safetyMargin, tiltAxis);
        };
        recalc();
        const onResize = () => recalc();
        window.addEventListener("resize", onResize);
        return () => window.removeEventListener("resize", onResize);
    }, [maxTiltDeg, safetyMargin, tiltAxis]);

    useEffect(() => {
        const onMouseMove = (e: MouseEvent) => {
            // считаем смещение относительно центра вьюпорта
            const cx = window.innerWidth / 2;
            const cy = window.innerHeight / 2;
            const dx = (e.clientX - cx) / (window.innerWidth / 2);  // -1..1
            const dy = (e.clientY - cy) / (window.innerHeight / 2); // -1..1
            const nx = Math.max(-1, Math.min(1, dx));
            const ny = Math.max(-1, Math.min(1, dy));

            targetRef.current.ry = (tiltAxis === 'both' || tiltAxis === 'horizontal') ? nx * maxTiltDeg : 0;   // вокруг Y — влево/вправо
            targetRef.current.rx = (tiltAxis === 'both' || tiltAxis === 'vertical') ? -ny * maxTiltDeg : 0;   // вокруг X — вверх/вниз
            targetRef.current.scale = isHoverRef.current ? hoverScale : 1;
        };

        const onEnter = () => (isHoverRef.current = true);
        const onLeave = () => {
            isHoverRef.current = false;
            targetRef.current.rx = 0;
            targetRef.current.ry = 0;
            targetRef.current.scale = 1;
        };

        document.addEventListener("mousemove", onMouseMove);
        document.addEventListener("mouseenter", onEnter);
        document.addEventListener("mouseleave", onLeave);

        const tick = () => {
            const el = planeRef.current;
            if (!el) return;

            const cur = currentRef.current;
            const tgt = targetRef.current;

            cur.rx += (tgt.rx - cur.rx) * ease;
            cur.ry += (tgt.ry - cur.ry) * ease;
            cur.scale += (tgt.scale - cur.scale) * ease;

            const base = baseScaleRef.current;
            const totalScale = base * cur.scale;

            el.style.transform = `
        perspective(${perspective}px)
        rotateX(${cur.rx}deg)
        rotateY(${cur.ry}deg)
        scale(${totalScale})
      `;

            rafRef.current = requestAnimationFrame(tick);
        };
        rafRef.current = requestAnimationFrame(tick);

        return () => {
            if (rafRef.current) cancelAnimationFrame(rafRef.current);
            document.removeEventListener("mousemove", onMouseMove);
            document.removeEventListener("mouseenter", onEnter);
            document.removeEventListener("mouseleave", onLeave);
        };
    }, [ease, hoverScale, maxTiltDeg, perspective, tiltAxis]);

    return (
        <>
            {/* слой-контейнер: фиксированный, во всю область, прячет края */}
            <div
                style={{
                    position: "absolute",
                    inset: 0,
                    overflow: "hidden",
                    zIndex: 1, // фон под контентом
                    pointerEvents: "none", // не блокирует клики по контенту
                    background: "#000",
                }}
            >
                {/* «плоскость», которую наклоняем и скейлим с оверсканом */}
                <div
                    ref={planeRef}
                    style={{
                        width: "100vw",
                        height: "100vh",
                        transformOrigin: "center center",
                        willChange: "transform",
                        filter: filterCss,
                    }}
                >
                    {/* сам фоновый кадр */}
                    <img
                        src={imageUrl}
                        alt=""
                        draggable={false}
                        style={{
                            width: "100%",
                            height: "100%",
                            display: "block",
                            objectFit: "cover",     // всегда покрывать экран
                            userSelect: "none",
                            backfaceVisibility: "hidden",
                            pointerEvents: "none",
                        }}
                    />
                </div>
            </div>
        </>
    );
};

export default Tilt3DImage;