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

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

export type FullscreenTiltBackdropProps = {
    imageUrl: string;
    maxTiltDeg?: number;
    tiltAxis?: TiltAxis;
    perspective?: number;
    hoverScale?: number;
    /** Инерция следования (0..1). Меньше — плавнее, «как в масле». */
    ease?: number;
    /** Инерция возврата в центр при уходе курсора (обычно меньше ease) */
    returnEase?: number;
    safetyMargin?: number;
    filterCss?: string;
    /** Цвет бренда для aurora / glow / particles */
    brandColor?: string;

    enableGradientOverlay?: boolean;
    enableSpotlight?: boolean;
    enableKenBurns?: boolean;
    enableDualLayer?: boolean;
    enableFilmGrain?: boolean;
    enableVignette?: boolean;
    enableDynamicBlur?: boolean;
    enableDynamicFilter?: boolean;
    /** Плавающие анимированные «орбы» за кадром */
    enableAurora?: boolean;
    /** RGB-разделение по краям при наклоне */
    enableChromaticAberration?: boolean;
    /** Светящиеся частицы */
    enableParticles?: boolean;
    /** Диагональная вспышка света */
    enableShimmer?: boolean;
    /** Сдвиг кадра внутри плоскости (глубина) */
    enableDepthParallax?: boolean;
    /** Пульсирующее свечение в покое */
    enableAmbientGlow?: boolean;
    /** Тёплые блики по углам */
    enableLightLeak?: boolean;

    spotlightRadius?: number;
    kenBurnsDuration?: number;
    kenBurnsIdleMs?: number;
    dualLayerBlur?: number;
    dualLayerParallaxFactor?: number;
    particleCount?: number;
    depthParallaxPx?: number;
};

const GRAIN_SVG =
    "url(\"data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E\")";

const GRADIENT_OVERLAY_STYLE: React.CSSProperties = {
    position: 'absolute',
    inset: 0,
    zIndex: 6,
    pointerEvents: 'none',
    background: `
      radial-gradient(ellipse 85% 65% at 72% 48%, transparent 0%, rgba(0,0,0,0.4) 68%),
      linear-gradient(108deg, rgba(0,0,0,0.82) 0%, rgba(0,0,0,0.12) 40%, rgba(0,0,0,0.6) 100%)
    `,
};

const AURORA_BLOBS = [
    { left: '8%', top: '12%', size: '55vw', delay: '0s', duration: '18s' },
    { left: '62%', top: '58%', size: '48vw', delay: '-6s', duration: '22s' },
    { left: '38%', top: '78%', size: '42vw', delay: '-12s', duration: '20s' },
] as const;

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);
};

const buildPlaneTransform = (
    perspective: number,
    rx: number,
    ry: number,
    scale: number,
) =>
    `perspective(${perspective}px) rotateX(${rx}deg) rotateY(${ry}deg) scale(${scale})`;

/** Сглаживание, не зависящее от FPS: меньше factor — вязче */
const lerpInertia = (current: number, target: number, factor: number, dtMs: number) => {
    const t = 1 - Math.pow(1 - factor, dtMs / 16.67);
    return current + (target - current) * t;
};

const hexToRgb = (hex: string): [number, number, number] | null => {
    const h = hex.replace('#', '').trim();
    if (h.length !== 3 && h.length !== 6) return null;
    const full =
        h.length === 3
            ? h
                  .split('')
                  .map((c) => c + c)
                  .join('')
            : h;
    const n = parseInt(full, 16);
    if (Number.isNaN(n)) return null;
    return [(n >> 16) & 255, (n >> 8) & 255, n & 255];
};

const colorAlpha = (color: string | undefined, alpha: number, fallback: string) => {
    if (!color) return fallback;
    const rgb = hexToRgb(color);
    if (!rgb) return fallback;
    return `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, ${alpha})`;
};

type ParticleSpec = {
    id: number;
    left: number;
    top: number;
    size: number;
    delay: number;
    duration: number;
    opacity: number;
};

const makeParticles = (count: number): ParticleSpec[] =>
    Array.from({ length: count }, (_, i) => ({
        id: i,
        left: Math.random() * 100,
        top: Math.random() * 100,
        size: 1 + Math.random() * 3,
        delay: Math.random() * 8,
        duration: 6 + Math.random() * 10,
        opacity: 0.15 + Math.random() * 0.45,
    }));

const Tilt3DImage: React.FC<FullscreenTiltBackdropProps> = ({
    imageUrl,
    maxTiltDeg = 14,
    tiltAxis = 'both',
    perspective = 1100,
    hoverScale = 1.05,
    ease = 0.028,
    returnEase = 0.018,
    safetyMargin = 0.3,
    filterCss,
    brandColor,

    enableGradientOverlay = true,
    enableSpotlight = true,
    enableKenBurns = true,
    enableDualLayer = true,
    enableFilmGrain = true,
    enableVignette = true,
    enableDynamicBlur = true,
    enableDynamicFilter = true,
    enableAurora = true,
    enableChromaticAberration = true,
    enableParticles = true,
    enableShimmer = true,
    enableDepthParallax = true,
    enableAmbientGlow = true,
    enableLightLeak = true,

    spotlightRadius = 720,
    kenBurnsDuration = 22,
    kenBurnsIdleMs = 2200,
    dualLayerBlur = 28,
    dualLayerParallaxFactor = 0.35,
    particleCount = 36,
    depthParallaxPx = 28,
}) => {
    const planeRef = useRef<HTMLDivElement | null>(null);
    const backPlaneRef = useRef<HTMLDivElement | null>(null);
    const imgWrapRef = useRef<HTMLDivElement | null>(null);
    const imgRef = useRef<HTMLImageElement | null>(null);
    const spotlightRef = useRef<HTMLDivElement | null>(null);
    const ambientGlowRef = useRef<HTMLDivElement | null>(null);

    const isHoverRef = useRef(false);
    const rafRef = useRef<number | null>(null);
    const baseScaleRef = useRef(1);
    const lastFrameRef = useRef(performance.now());
    /** Цель с курсора (мгновенно) */
    const rawRef = useRef({
        x: 50,
        y: 50,
        nx: 0,
        ny: 0,
        rx: 0,
        ry: 0,
        scale: 1,
        lastMove: Date.now(),
    });
    /** Сглаженное состояние — всё рисуем из него */
    const smoothRef = useRef({
        x: 50,
        y: 50,
        nx: 0,
        ny: 0,
        rx: 0,
        ry: 0,
        scale: 1,
    });
    const startTimeRef = useRef(Date.now());

    const particles = useMemo(
        () => makeParticles(particleCount),
        [particleCount],
    );

    const auroraColor = colorAlpha(brandColor, 0.45, 'rgba(99, 102, 241, 0.45)');
    const auroraColorSoft = colorAlpha(brandColor, 0.22, 'rgba(139, 92, 246, 0.22)');
    const particleColor = colorAlpha(brandColor, 0.85, 'rgba(255, 255, 255, 0.85)');
    const glowColor = colorAlpha(brandColor, 0.35, 'rgba(120, 140, 255, 0.35)');

    useEffect(() => {
        const recalc = () => {
            baseScaleRef.current = computeBaseScale(maxTiltDeg, safetyMargin, tiltAxis);
        };
        recalc();
        window.addEventListener('resize', recalc);
        return () => window.removeEventListener('resize', recalc);
    }, [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);
            const dy = (e.clientY - cy) / (window.innerHeight / 2);
            const nx = Math.max(-1, Math.min(1, dx));
            const ny = Math.max(-1, Math.min(1, dy));

            rawRef.current.x = (e.clientX / window.innerWidth) * 100;
            rawRef.current.y = (e.clientY / window.innerHeight) * 100;
            rawRef.current.nx = nx;
            rawRef.current.ny = ny;
            rawRef.current.lastMove = Date.now();

            rawRef.current.ry =
                tiltAxis === 'both' || tiltAxis === 'horizontal' ? nx * maxTiltDeg : 0;
            rawRef.current.rx =
                tiltAxis === 'both' || tiltAxis === 'vertical' ? -ny * maxTiltDeg : 0;
            rawRef.current.scale = isHoverRef.current ? hoverScale : 1;
        };

        const onEnter = () => {
            isHoverRef.current = true;
        };
        const onLeave = () => {
            isHoverRef.current = false;
            rawRef.current.x = 50;
            rawRef.current.y = 50;
            rawRef.current.nx = 0;
            rawRef.current.ny = 0;
            rawRef.current.rx = 0;
            rawRef.current.ry = 0;
            rawRef.current.scale = 1;
        };

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

        const tick = (now: number) => {
            const el = planeRef.current;
            const dtMs = Math.min(48, now - lastFrameRef.current);
            lastFrameRef.current = now;

            if (!el) {
                rafRef.current = requestAnimationFrame(tick);
                return;
            }

            const raw = rawRef.current;
            const sm = smoothRef.current;
            const atRest =
                raw.nx === 0 &&
                raw.ny === 0 &&
                raw.rx === 0 &&
                raw.ry === 0 &&
                raw.scale === 1;
            const follow = atRest ? returnEase : ease;

            sm.x = lerpInertia(sm.x, raw.x, follow, dtMs);
            sm.y = lerpInertia(sm.y, raw.y, follow, dtMs);
            sm.nx = lerpInertia(sm.nx, raw.nx, follow, dtMs);
            sm.ny = lerpInertia(sm.ny, raw.ny, follow, dtMs);
            sm.rx = lerpInertia(sm.rx, raw.rx, follow, dtMs);
            sm.ry = lerpInertia(sm.ry, raw.ry, follow, dtMs);
            sm.scale = lerpInertia(sm.scale, raw.scale, follow, dtMs);

            const base = baseScaleRef.current;
            const totalScale = base * sm.scale;
            const tiltMag = Math.abs(sm.rx) + Math.abs(sm.ry);
            const velocity = Math.hypot(raw.rx - sm.rx, raw.ry - sm.ry);
            const t = (Date.now() - startTimeRef.current) / 1000;

            el.style.transform = buildPlaneTransform(
                perspective,
                sm.rx,
                sm.ry,
                totalScale,
            );

            if (enableDualLayer && backPlaneRef.current) {
                const factor = dualLayerParallaxFactor;
                backPlaneRef.current.style.transform = buildPlaneTransform(
                    perspective,
                    sm.rx * factor,
                    sm.ry * factor,
                    totalScale * 1.1,
                );
            }

            const filters: string[] = [];
            if (filterCss) filters.push(filterCss);
            if (enableDynamicFilter) {
                filters.push(
                    `saturate(${1.15 + tiltMag * 0.01})`,
                    `contrast(${1.05 + velocity * 0.003})`,
                    `brightness(${1.02 + velocity * 0.01})`,
                );
            }
            if (enableDynamicBlur) {
                filters.push(`blur(${Math.min(2.5, tiltMag * 0.08)}px)`);
            }
            if (enableChromaticAberration) {
                const ca = Math.min(4, tiltMag * 0.22 + velocity * 0.15);
                filters.push(
                    `drop-shadow(${ca * (sm.ry / 14)}px ${ca * 0.25}px 0 rgba(255,70,90,0.35))`,
                    `drop-shadow(${-ca * (sm.ry / 14)}px ${-ca * 0.2}px 0 rgba(60,200,255,0.32))`,
                );
            }
            el.style.filter = filters.length ? filters.join(' ') : 'none';

            if (enableSpotlight && spotlightRef.current) {
                spotlightRef.current.style.background = `
          radial-gradient(${spotlightRadius * 0.35}px circle at ${sm.x}% ${sm.y}%, rgba(255,255,255,0.22) 0%, transparent 45%),
          radial-gradient(${spotlightRadius}px circle at ${sm.x}% ${sm.y}%, rgba(255,255,255,0.12) 0%, transparent 58%)
        `;
            }

            if (enableAmbientGlow && ambientGlowRef.current) {
                const pulse = 0.5 + 0.5 * Math.sin(t * 0.8);
                ambientGlowRef.current.style.opacity = String(0.35 + pulse * 0.25);
                ambientGlowRef.current.style.transform = `translate(${sm.nx * 12}px, ${sm.ny * 8}px)`;
            }

            if (enableDepthParallax && imgRef.current) {
                imgRef.current.style.transform = `translate3d(${sm.nx * depthParallaxPx}px, ${sm.ny * depthParallaxPx * 0.7}px, 0) scale(1.1)`;
            }

            if (enableKenBurns && imgWrapRef.current) {
                const idle = Date.now() - raw.lastMove > kenBurnsIdleMs;
                imgWrapRef.current.style.animation = idle
                    ? `tilt3dKenBurns ${kenBurnsDuration}s ease-in-out infinite`
                    : 'none';
            }

            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);
        };
    }, [
        depthParallaxPx,
        dualLayerParallaxFactor,
        ease,
        returnEase,
        enableAmbientGlow,
        enableChromaticAberration,
        enableDepthParallax,
        enableDualLayer,
        enableDynamicBlur,
        enableDynamicFilter,
        enableKenBurns,
        enableSpotlight,
        filterCss,
        hoverScale,
        kenBurnsDuration,
        kenBurnsIdleMs,
        maxTiltDeg,
        perspective,
        spotlightRadius,
        tiltAxis,
    ]);

    const planeStyle: React.CSSProperties = {
        position: 'absolute',
        inset: 0,
        width: '100%',
        height: '100%',
        transformOrigin: 'center center',
        willChange: 'transform',
    };

    const imgStyle: React.CSSProperties = {
        width: '100%',
        height: '100%',
        display: 'block',
        objectFit: 'cover',
        userSelect: 'none',
        backfaceVisibility: 'hidden',
        pointerEvents: 'none',
        willChange: 'transform',
    };

    return (
        <>
            <style>{`
        @keyframes tilt3dKenBurns {
          0%, 100% { transform: scale(1) translate(0, 0); }
          33% { transform: scale(1.05) translate(-1.2%, -0.6%); }
          66% { transform: scale(1.07) translate(0.8%, 0.4%); }
        }
        @keyframes tilt3dAuroraFloat {
          0%, 100% { transform: translate(0, 0) scale(1); }
          33% { transform: translate(4%, -3%) scale(1.08); }
          66% { transform: translate(-3%, 5%) scale(0.95); }
        }
        @keyframes tilt3dShimmerSweep {
          0% { transform: translateX(-120%) skewX(-12deg); opacity: 0; }
          15% { opacity: 0.5; }
          50% { opacity: 0.35; }
          100% { transform: translateX(220%) skewX(-12deg); opacity: 0; }
        }
        @keyframes tilt3dParticleFloat {
          0%, 100% { transform: translateY(0) translateX(0); opacity: 0.2; }
          50% { transform: translateY(-28px) translateX(12px); opacity: 0.9; }
        }
        @keyframes tilt3dLightLeakPulse {
          0%, 100% { opacity: 0.25; }
          50% { opacity: 0.55; }
        }
      `}</style>

            <div
                style={{
                    position: 'absolute',
                    inset: 0,
                    overflow: 'hidden',
                    zIndex: 1,
                    pointerEvents: 'none',
                    background: '#000',
                }}
            >
                {enableAurora &&
                    AURORA_BLOBS.map((blob, i) => (
                        <div
                            key={i}
                            style={{
                                position: 'absolute',
                                left: blob.left,
                                top: blob.top,
                                width: blob.size,
                                height: blob.size,
                                borderRadius: '50%',
                                background: `radial-gradient(circle, ${i % 2 === 0 ? auroraColor : auroraColorSoft} 0%, transparent 70%)`,
                                filter: 'blur(60px)',
                                animation: `tilt3dAuroraFloat ${blob.duration} ease-in-out infinite`,
                                animationDelay: blob.delay,
                                zIndex: 0,
                            }}
                        />
                    ))}

                {enableDualLayer && (
                    <div
                        ref={backPlaneRef}
                        style={{
                            ...planeStyle,
                            zIndex: 1,
                            filter: `blur(${dualLayerBlur}px) saturate(1.2)`,
                            opacity: 0.5,
                        }}
                    >
                        <img src={imageUrl} alt="" draggable={false} style={imgStyle} />
                    </div>
                )}

                <div ref={planeRef} style={{ ...planeStyle, zIndex: 2 }}>
                    <div
                        ref={imgWrapRef}
                        style={{
                            width: '100%',
                            height: '100%',
                            overflow: 'hidden',
                        }}
                    >
                        <img
                            ref={imgRef}
                            src={imageUrl}
                            alt=""
                            draggable={false}
                            style={imgStyle}
                        />
                    </div>
                </div>

                {enableVignette && (
                    <div
                        style={{
                            position: 'absolute',
                            inset: 0,
                            zIndex: 3,
                            pointerEvents: 'none',
                            boxShadow:
                                'inset 0 0 160px rgba(0,0,0,0.65), inset 0 0 60px rgba(0,0,0,0.25)',
                        }}
                    />
                )}

                {enableFilmGrain && (
                    <div
                        style={{
                            position: 'absolute',
                            inset: 0,
                            zIndex: 4,
                            pointerEvents: 'none',
                            opacity: 0.05,
                            mixBlendMode: 'overlay',
                            backgroundImage: GRAIN_SVG,
                            backgroundSize: '160px 160px',
                        }}
                    />
                )}

                {enableLightLeak && (
                    <>
                        <div
                            style={{
                                position: 'absolute',
                                top: -10,
                                right: -5,
                                width: '45%',
                                height: '40%',
                                zIndex: 5,
                                pointerEvents: 'none',
                                background: `radial-gradient(ellipse at 100% 0%, ${colorAlpha(brandColor, 0.35, 'rgba(255,180,100,0.35)')} 0%, transparent 65%)`,
                                animation: 'tilt3dLightLeakPulse 8s ease-in-out infinite',
                            }}
                        />
                        <div
                            style={{
                                position: 'absolute',
                                bottom: -5,
                                left: -5,
                                width: '40%',
                                height: '35%',
                                zIndex: 5,
                                pointerEvents: 'none',
                                background: `radial-gradient(ellipse at 0% 100%, ${colorAlpha(brandColor, 0.28, 'rgba(100,160,255,0.28)')} 0%, transparent 70%)`,
                                animation: 'tilt3dLightLeakPulse 11s ease-in-out infinite reverse',
                            }}
                        />
                    </>
                )}

                {enableGradientOverlay && <div style={GRADIENT_OVERLAY_STYLE} />}

                {enableAmbientGlow && (
                    <div
                        ref={ambientGlowRef}
                        style={{
                            position: 'absolute',
                            left: '50%',
                            top: '55%',
                            width: '70%',
                            height: '50%',
                            marginLeft: '-35%',
                            marginTop: '-25%',
                            zIndex: 7,
                            pointerEvents: 'none',
                            background: `radial-gradient(ellipse at center, ${glowColor} 0%, transparent 70%)`,
                            filter: 'blur(40px)',
                            transition: 'opacity 0.3s ease',
                        }}
                    />
                )}

                {enableSpotlight && (
                    <div
                        ref={spotlightRef}
                        style={{
                            position: 'absolute',
                            inset: 0,
                            zIndex: 8,
                            pointerEvents: 'none',
                            mixBlendMode: 'soft-light',
                        }}
                    />
                )}

                {enableShimmer && (
                    <div
                        style={{
                            position: 'absolute',
                            inset: 0,
                            zIndex: 9,
                            pointerEvents: 'none',
                            overflow: 'hidden',
                        }}
                    >
                        <div
                            style={{
                                position: 'absolute',
                                top: '-20%',
                                left: 0,
                                width: '40%',
                                height: '140%',
                                background:
                                    'linear-gradient(105deg, transparent 0%, rgba(255,255,255,0.06) 45%, rgba(255,255,255,0.18) 50%, rgba(255,255,255,0.06) 55%, transparent 100%)',
                                animation: 'tilt3dShimmerSweep 7s ease-in-out infinite',
                            }}
                        />
                    </div>
                )}

                {enableParticles && (
                    <div
                        style={{
                            position: 'absolute',
                            inset: 0,
                            zIndex: 10,
                            pointerEvents: 'none',
                            overflow: 'hidden',
                        }}
                    >
                        {particles.map((p) => (
                            <div
                                key={p.id}
                                style={{
                                    position: 'absolute',
                                    left: `${p.left}%`,
                                    top: `${p.top}%`,
                                    width: p.size,
                                    height: p.size,
                                    borderRadius: '50%',
                                    background: particleColor,
                                    boxShadow: `0 0 ${p.size * 4}px ${particleColor}`,
                                    opacity: p.opacity,
                                    animation: `tilt3dParticleFloat ${p.duration}s ease-in-out infinite`,
                                    animationDelay: `${p.delay}s`,
                                }}
                            />
                        ))}
                    </div>
                )}
            </div>
        </>
    );
};

export default Tilt3DImage;
