import Lenis from 'lenis';
import gsap from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
import { ReducedMotionChecker } from './ReducedMotionChecker';

/**
 * The `lenis` package's own type declarations claim `Window.lenis` for its
 * devtools-detection marker (a small `{version, horizontal, snap, touch}`
 * object), so the real Lenis instance stashed here for cross-module access
 * (see BurgerMenu.ts) can't be typed via declaration merging - this local
 * cast type is shared instead.
 */
export type WindowWithLenis = { lenis?: Lenis };

// Register GSAP plugin with error boundary
try {
    gsap.registerPlugin(ScrollTrigger);
} catch (error) {
    console.error('Failed to register GSAP ScrollTrigger plugin:', error);
    throw new Error('GSAP ScrollTrigger plugin registration failed. Smooth scroll sync will not work.', { cause: error });
}

export class SmoothScroll {
    private lenis: Lenis | null = null;
    private tickerFn: ((time: number) => void) | null = null;
    private checker = new ReducedMotionChecker();
    private matchMedia: gsap.MatchMedia | null = null;

    public initialize(): void {
        if (this.checker.shouldReduceMotion()) {
            console.log('[SmoothScroll] Skipped - prefers-reduced-motion');
            return;
        }

        this.matchMedia = gsap.matchMedia();

        this.matchMedia.add("(min-width: 1024px)", () => {
            this.lenis = new Lenis({
                duration: 1.2,
                easing: (t: number) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
                orientation: 'vertical',
                smoothWheel: true,
                wheelMultiplier: 1,
                infinite: false,
            });

            // Keep ScrollTrigger's measurements in sync with Lenis's smoothed
            // scroll position — required for accurate pin/scrub effects
            // (see assets/animations/gsap/HorizontalPinScroll.ts).
            this.lenis.on('scroll', ScrollTrigger.update);

            this.tickerFn = (time: number) => {
                this.lenis?.raf(time * 1000);
            };
            gsap.ticker.add(this.tickerFn);
            gsap.ticker.lagSmoothing(0);
            (window as unknown as WindowWithLenis).lenis = this.lenis;

            return () => {
                // Cleanup function for matchMedia
                this.destroy();
            };
        });
    }

    public destroy(): void {
        if (this.tickerFn) {
            gsap.ticker.remove(this.tickerFn);
            this.tickerFn = null;
        }
        this.lenis?.destroy();
        this.lenis = null;
        (window as unknown as WindowWithLenis).lenis = undefined;
    }
}

// Export legacy function for backwards compatibility during migration
export function initSmoothScroll(): void {
    const smoothScroll = new SmoothScroll();
    smoothScroll.initialize();
}

export function destroySmoothScroll(): void {
    const win = window as unknown as WindowWithLenis;
    if (win.lenis) {
        win.lenis.destroy();
        win.lenis = undefined;
    }
}
