'use client';

import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
import Lenis from 'lenis';
import { DEFAULT_EASE, DEFAULT_DURATION } from '@/utils/animation';
import Link from 'next/link';
import ProblemsShift from '@/components/home/ProblemsShift';
import WhatWeDo from '@/components/home/WhatWeDo';
import ProductsSection from '@/components/home/ProductsSection';
import TheLoop from '@/components/home/TheLoop';
import initGlobalReveal from '@/utils/scrollReveal';

const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;

if (typeof window !== 'undefined') {
  gsap.registerPlugin(ScrollTrigger);
}

export default function IndexPage() {
  const [imagesLoaded, setImagesLoaded] = useState(false);
  const [loadProgress, setLoadProgress] = useState(0);

  const containerRef  = useRef<HTMLDivElement | null>(null);
  const heroRef       = useRef<HTMLDivElement | null>(null);
  const canvasRef     = useRef<HTMLCanvasElement | null>(null);
  const overlayRef    = useRef<HTMLDivElement | null>(null);
  const preloaderRef  = useRef<HTMLDivElement | null>(null);
  const welcomeRef    = useRef<HTMLDivElement | null>(null);

  const imagesRef            = useRef<HTMLImageElement[]>([]);
  const currentFrameIndexRef = useRef<number>(0);
  const canvasWidthRef       = useRef<number>(0);
  const canvasHeightRef      = useRef<number>(0);
  // tracks loaded count without re-rendering on every frame
  const loadedCountRef       = useRef<number>(0);

  const frameCount = 192;

  /* ── draw ─────────────────────────────────────────────────────── */
  const drawFrame = useCallback((frameIndex: number) => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    if (!ctx) return;
    const img = imagesRef.current[frameIndex];
    if (!img) return;

    let canvasWidth  = canvasWidthRef.current;
    let canvasHeight = canvasHeightRef.current;
    if (canvasWidth === 0 || canvasHeight === 0) {
      canvasWidth  = canvas.offsetWidth;
      canvasHeight = canvas.offsetHeight;
      canvasWidthRef.current  = canvasWidth;
      canvasHeightRef.current = canvasHeight;
    }

    const imgWidth  = img.naturalWidth  || img.width;
    const imgHeight = img.naturalHeight || img.height;
    if (imgWidth && imgHeight) {
      const imgRatio    = imgWidth / imgHeight;
      const canvasRatio = canvasWidth / canvasHeight;
      let drawWidth  = canvasWidth;
      let drawHeight = canvasHeight;
      let offsetX = 0;
      let offsetY = 0;
      if (canvasRatio > imgRatio) {
        drawHeight = canvasWidth / imgRatio;
        offsetY    = (canvasHeight - drawHeight) / 2;
      } else {
        drawWidth = canvasHeight * imgRatio;
        offsetX   = (canvasWidth - drawWidth) / 2;
      }
      ctx.clearRect(0, 0, canvasWidth, canvasHeight);
      ctx.drawImage(img, offsetX, offsetY, drawWidth, drawHeight);
    }
  }, []);

  /* ── resize ───────────────────────────────────────────────────── */
  const handleResize = useCallback(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const dpr = window.devicePixelRatio || 1;
    const logicalWidth  = canvas.offsetWidth;
    const logicalHeight = canvas.offsetHeight;
    canvasWidthRef.current  = logicalWidth;
    canvasHeightRef.current = logicalHeight;
    canvas.width  = logicalWidth  * dpr;
    canvas.height = logicalHeight * dpr;
    const ctx = canvas.getContext('2d');
    if (ctx) {
      ctx.setTransform(1, 0, 0, 1, 0, 0);
      ctx.scale(dpr, dpr);
    }
    drawFrame(currentFrameIndexRef.current);
  }, [drawFrame]);

  /* ── lock scroll until preloader exits ───────────────────────── */
  useEffect(() => {
    document.body.style.overflow = 'hidden';
    return () => { document.body.style.overflow = ''; };
  }, []);

  /* ── load frame 0 immediately (canvas visible behind preloader) ─ */
  useEffect(() => {
    const firstImg = new Image();
    firstImg.onload = () => {
      if (imagesRef.current.length === 0) {
        imagesRef.current = [firstImg];
        const canvas = canvasRef.current;
        if (canvas) {
          const dpr = window.devicePixelRatio || 1;
          canvas.width  = canvas.offsetWidth  * dpr;
          canvas.height = canvas.offsetHeight * dpr;
          const ctx = canvas.getContext('2d');
          if (ctx) { ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.scale(dpr, dpr); }
          drawFrame(0);
        }
      }
    };
    firstImg.src = '/img_frames/frame_000_delay-0.041s.jpg';
  }, [drawFrame]);

  /* ── preload all frames, update progress counter ─────────────── */
  useEffect(() => {
    // Reset counter every time this effect runs (guards against Strict Mode
    // double-invocation and any navigation-back scenario that re-mounts the component)
    loadedCountRef.current = 0;

    const images: HTMLImageElement[] = [];

    // Use RAF-throttled progress updates to avoid 192 rapid re-renders
    let rafId = 0;
    const scheduleUpdate = (pct: number, done: boolean) => {
      cancelAnimationFrame(rafId);
      rafId = requestAnimationFrame(() => {
        setLoadProgress(pct);
        if (done) {
          imagesRef.current = images;
          setImagesLoaded(true);
        }
      });
    };

    for (let i = 0; i < frameCount; i++) {
      const img = new Image();
      const paddedIndex = String(i).padStart(3, '0');
      const onLoad = () => {
        loadedCountRef.current++;
        const pct  = Math.min(100, Math.round((loadedCountRef.current / frameCount) * 100));
        const done = loadedCountRef.current >= frameCount;
        scheduleUpdate(pct, done);
      };
      img.onload  = onLoad;
      img.onerror = onLoad;
      img.src = `/img_frames/frame_${paddedIndex}_delay-0.041s.jpg`;
      images.push(img);
    }

    return () => {
      cancelAnimationFrame(rafId);
      // Reset so a re-run (Strict Mode or re-mount) always starts clean
      loadedCountRef.current = 0;
    };
  }, []);

  /* ── resize listener ──────────────────────────────────────────── */
  useEffect(() => {
    window.addEventListener('resize', handleResize);
    handleResize();
    return () => window.removeEventListener('resize', handleResize);
  }, [handleResize, imagesLoaded]);

  /* ── ScrollTrigger refresh after all frames load ──────────────── */
  useEffect(() => {
    if (!imagesLoaded) return;
    ScrollTrigger.sort(); ScrollTrigger.refresh(); handleResize();
    const t1 = setTimeout(() => { ScrollTrigger.sort(); ScrollTrigger.refresh(); handleResize(); }, 200);
    const t2 = setTimeout(() => { ScrollTrigger.sort(); ScrollTrigger.refresh(); }, 600);
    return () => { clearTimeout(t1); clearTimeout(t2); };
  }, [imagesLoaded, handleResize]);

  /* ── animate preloader out when all frames are ready ─────────── */
  useEffect(() => {
    if (!imagesLoaded) return;
    const preloader = preloaderRef.current;
    if (!preloader) return;

    const tl = gsap.timeline({
      delay: 0.2,
      onComplete: () => {
        preloader.style.display = 'none';
        document.body.style.overflow = '';
      },
    });

    tl.to('.pl-number',  { opacity: 0, y: -50, duration: 0.55, ease: 'power3.in' },  0)
      .to('.pl-pct',     { opacity: 0, duration: 0.4, ease: 'power2.in' },             0.05)
      .to('.pl-label',   { opacity: 0, duration: 0.4, ease: 'power2.in' },             0.1)
      .to('.pl-bar',     { scaleX: 1, duration: 0.25, ease: 'power3.out' },            0)
      .to(preloader,     { yPercent: -100, duration: 1.05, ease: 'expo.inOut' },       0.4);

    // Kill the timeline on unmount so stale onComplete never runs after navigation
    return () => { tl.kill(); };
  }, [imagesLoaded]);

  /* ── homepage header show/hide on scroll direction ───────────── */
  useEffect(() => {
    document.body.classList.add('is-home-page', 'scroll-down');
    const DELTA = 6;
    let lastY = window.scrollY;
    let ticking = false;
    const onScroll = () => {
      if (ticking) return;
      window.requestAnimationFrame(() => {
        const y     = window.scrollY;
        const delta = y - lastY;
        if (y <= 100) {
          document.body.classList.add('scroll-down');
          document.body.classList.remove('scroll-up');
        } else if (Math.abs(delta) >= DELTA) {
          if (delta > 0) {
            document.body.classList.add('scroll-down');
            document.body.classList.remove('scroll-up');
          } else {
            document.body.classList.add('scroll-up');
            document.body.classList.remove('scroll-down');
          }
        }
        lastY   = y;
        ticking = false;
      });
      ticking = true;
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => {
      document.body.classList.remove('is-home-page', 'scroll-down', 'scroll-up');
      window.removeEventListener('scroll', onScroll);
    };
  }, []);

  /* ── Lenis + GSAP scrub (frame seq + welcome text + hero text) ── */
  useIsomorphicLayoutEffect(() => {
    if (!imagesLoaded) return;

    const lenis = new Lenis({
      duration: 1.2,
      easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
      smoothWheel: true,
    });
    lenis.on('scroll', ScrollTrigger.update);
    const updateTicker = (time: number) => lenis.raf(time * 1000);
    gsap.ticker.add(updateTicker);
    gsap.ticker.lagSmoothing(0);

    const cleanupReveal = initGlobalReveal();
    const air = { frame: 0 };

    const ctx = gsap.context(() => {
      const tl = gsap.timeline({
        scrollTrigger: {
          trigger: containerRef.current,
          start: 'top top',
          end: '+=300%',
          pin: true,
          pinType: 'transform',
          scrub: true,
          anticipatePin: 1,
          invalidateOnRefresh: true,
          refreshPriority: 10,
        },
      });

      // Frame scrub (full duration = 1.0)
      tl.to(air, {
        frame: frameCount - 1,
        ease: 'none',
        duration: 1.0,
        onUpdate: () => {
          const f = Math.floor(air.frame);
          currentFrameIndexRef.current = f;
          drawFrame(f);
        },
      }, 0);

      // "Welcome Buddy" text: visible at frame 0, fades OUT by frame 25
      const welcomeEnd = 25 / (frameCount - 1); // ≈ 0.131
      if (welcomeRef.current) {
        tl.fromTo(
          welcomeRef.current,
          { opacity: 1, y: 0, scale: 1 },
          { opacity: 0, y: -28, scale: 0.93, ease: 'power2.in', duration: welcomeEnd },
          0
        );
      }

      // Hero text + white overlay: fade IN starting at frame 120
      const startProgress = 120 / (frameCount - 1);
      const fadeDuration  = 30  / (frameCount - 1);

      if (heroRef.current) {
        tl.to(heroRef.current,  { opacity: 1, y: 0, ease: DEFAULT_EASE, duration: fadeDuration || DEFAULT_DURATION }, startProgress);
      }
      if (overlayRef.current) {
        tl.to(overlayRef.current, { opacity: 1, ease: DEFAULT_EASE, duration: fadeDuration || DEFAULT_DURATION },     startProgress);
      }
    });

    return () => {
      ctx.revert();
      lenis.destroy();
      gsap.ticker.remove(updateTicker);
      if (typeof cleanupReveal === 'function') cleanupReveal();
    };
  }, [imagesLoaded, drawFrame]);

  /* ── render ───────────────────────────────────────────────────── */
  return (
    <>
      {/* ══════════════════════════════════════════
          PRELOADER
          Fixed overlay — slides up when images done
         ══════════════════════════════════════════ */}
      <div
        ref={preloaderRef}
        style={{
          position: 'fixed', inset: 0, zIndex: 9999,
          display: 'flex', flexDirection: 'column',
          alignItems: 'center', justifyContent: 'center',
          overflow: 'hidden',
        }}
      >
        {/* Background: frame_000 blurred + dark overlay */}
        <div style={{
          position: 'absolute', inset: 0,
          backgroundImage: `url('/img_frames/frame_000_delay-0.041s.jpg')`,
          backgroundSize: 'cover', backgroundPosition: 'center',
          filter: 'blur(3px)', transform: 'scale(1.06)',
        }} />
        <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(160deg,rgba(7,7,10,0.88) 0%,rgba(10,8,5,0.92) 100%)' }} />

        {/* Noise grain */}
        <div style={{
          position: 'absolute', inset: 0, opacity: 0.035, mixBlendMode: 'overlay',
          backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")`,
        }} />

        {/* Brand wordmark */}
        <div className="pl-label" style={{
          position: 'relative', zIndex: 2,
          fontSize: 11, fontWeight: 800, letterSpacing: '0.3em',
          textTransform: 'uppercase', color: 'rgba(244,190,40,0.75)',
          fontFamily: 'Sora, sans-serif', marginBottom: 36,
          userSelect: 'none',
        }}>
          Loyaly
        </div>

        {/* Big percentage counter */}
        <div style={{ position: 'relative', zIndex: 2, display: 'flex', alignItems: 'flex-start', gap: 6 }}>
          <span className="pl-number" style={{
            fontSize: 'clamp(88px, 14vw, 156px)',
            fontWeight: 900, lineHeight: 0.86,
            letterSpacing: '-0.05em', color: '#ffffff',
            fontFamily: 'Sora, sans-serif',
            fontVariantNumeric: 'tabular-nums',
            userSelect: 'none',
            willChange: 'transform, opacity',
          }}>
            {loadProgress}
          </span>
          <span className="pl-pct" style={{
            fontSize: 'clamp(22px, 3.5vw, 38px)',
            fontWeight: 800, color: 'rgba(255,255,255,0.35)',
            fontFamily: 'Sora, sans-serif', marginTop: 10,
            userSelect: 'none',
          }}>%</span>
        </div>

        {/* Sub-label */}
        <div className="pl-label" style={{
          position: 'relative', zIndex: 2,
          fontSize: 11, fontWeight: 600, letterSpacing: '0.2em',
          textTransform: 'uppercase', color: 'rgba(255,255,255,0.28)',
          fontFamily: 'Sora, sans-serif', marginTop: 28,
          userSelect: 'none',
        }}>
          Loading experience
        </div>

        {/* Progress bar (full width, bottom) */}
        <div className="pl-bar-track" style={{
          position: 'absolute', bottom: 0, left: 0, right: 0, height: 3,
          background: 'rgba(255,255,255,0.06)',
        }}>
          <div className="pl-bar" style={{
            height: '100%',
            width: `${loadProgress}%`,
            background: 'linear-gradient(90deg, #f4be28, #FF9800)',
            transition: 'width 0.12s linear',
            borderRadius: '0 2px 2px 0',
          }} />
        </div>
      </div>

      {/* ══════════════════════════════════════════
          HERO — pinned, drives canvas frame scrub
         ══════════════════════════════════════════ */}
      <main
        ref={containerRef}
        className="loyaly-home relative bg-white overflow-hidden"
        style={{
          width: 'calc(100% - 40px)',
          height: 'calc(100vh - 20px)',
          margin: '0 20px 20px',
          borderRadius: '25px',
        }}
      >
        {/* Canvas */}
        <div className="absolute inset-0 z-0 pointer-events-none" style={{ width: '100%', height: '100%' }}>
          <canvas ref={canvasRef} style={{ width: '100%', height: '100%', display: 'block' }} />
        </div>

        {/* ── "Welcome Buddy" — centered, visible at frame 0, fades by frame 25 ── */}
        <div
          ref={welcomeRef}
          style={{
            position: 'absolute', top: '50%', left: '50%',
            transform: 'translate(-50%, -50%)',
            zIndex: 12, textAlign: 'center',
            pointerEvents: 'none', userSelect: 'none',
            willChange: 'transform, opacity',
          }}
        >
          {/* Glow ring behind text */}
          <div style={{
            position: 'absolute', top: '50%', left: '50%',
            transform: 'translate(-50%, -50%)',
            width: 320, height: 120,
            background: 'radial-gradient(ellipse 60% 60% at 50% 50%, rgba(244,190,40,0.18) 0%, transparent 70%)',
            filter: 'blur(20px)',
            pointerEvents: 'none',
          }} />

          <p style={{
            margin: 0,
            fontSize: 'clamp(2rem, 4.5vw, 4.4rem)',
            fontWeight: 900,
            letterSpacing: '-0.04em',
            lineHeight: 1,
            color: '#ffffff',
            fontFamily: 'Sora, sans-serif',
            textShadow: '0 2px 32px rgba(0,0,0,0.5)',
            position: 'relative',
          }}>
            Welcome{' '}
            <span style={{
              background: 'linear-gradient(105deg,#f4be28 0%,#ffd95a 50%,#FF9800 100%)',
              WebkitBackgroundClip: 'text',
              WebkitTextFillColor: 'transparent',
            }}>Buddy</span>
          </p>

          <p style={{
            margin: '14px 0 0',
            fontSize: 'clamp(0.78rem, 1.1vw, 1rem)',
            fontWeight: 500,
            letterSpacing: '0.12em',
            textTransform: 'uppercase',
            color: 'rgba(255,255,255,0.42)',
            fontFamily: 'Sora, sans-serif',
            position: 'relative',
          }}>
            Scroll to explore
          </p>

          {/* Animated scroll chevron */}
          <div style={{ marginTop: 18, display: 'flex', justifyContent: 'center', position: 'relative' }}>
            <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="rgba(244,190,40,0.7)" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" className="animate-scroll-arrow">
              <path d="M19 13l-7 7-7-7m7-7v14" />
            </svg>
          </div>
        </div>

        {/* White shade behind the text content on the left only — right side stays fully clear (fades in with hero text at frame 120) */}
        <div
          ref={overlayRef}
          className="absolute inset-0 z-[5] pointer-events-none bg-gradient-to-r from-white/90 via-white/40 via-35% to-transparent to-55%"
          style={{ opacity: 0 }}
        />

        {/* Hero content (fades in at frame 120) */}
        <div
          ref={heroRef}
          className="absolute inset-y-0 left-0 z-10 flex items-center justify-start pointer-events-none h-full"
          style={{ opacity: 0, transform: 'translateY(30px)' }}
        >
          <div className="w-full lg:w-[50vw] px-8 sm:px-12 md:px-16 lg:pl-20 lg:pr-8 pointer-events-auto flex flex-col justify-center py-12 md:py-16">
            <h1 className="text-[#171512] hero-heading text-3xl sm:text-4xl md:text-5xl lg:text-5xl xl:text-6xl font-extrabold tracking-tight leading-[1.12] mb-6 select-none">
              Turn Every <br />
              Walk In Into a <br />
              <span className="hero-gradient-text">Loyal Customer</span>
            </h1>
            <p className="text-[#4f463a] hero-description text-sm sm:text-base md:text-lg xl:text-xl mb-8 leading-relaxed max-w-2xl select-none">
              Loyaly.ai turns everyday digital engagement into real world shopping rewards — customers earn coins through games and daily activities, then redeem them at offline stores near them.
            </p>
            <div className="flex flex-wrap gap-5">
              <Link href="/contacts" className="flex items-center gap-3 bg-[#f4be28] hover:bg-[#ffd95a] hero-btn-primary text-[#171512] px-8 py-4 rounded-xl font-bold text-base md:text-lg transition-all duration-300 shadow-lg shadow-yellow-500/30 hover:shadow-yellow-500/50 hover:scale-[1.02] cursor-pointer no-underline">
                Book a Demo
                <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.6} d="M14 5l7 7m0 0l-7 7m7-7H3" />
                </svg>
              </Link>
              <Link href="/contacts" className="flex items-center border-2 border-[#f4be28] hover:bg-[#f4be28]/15 hero-btn-secondary text-[#f4be28] px-8 py-4 rounded-xl font-bold text-base md:text-lg transition-all duration-300 hover:scale-[1.02] cursor-pointer no-underline">
                Get Started
              </Link>
            </div>
          </div>
        </div>
      </main>

      {/* Other sections */}
      <ProblemsShift isLoaded={imagesLoaded} />
      <WhatWeDo isLoaded={imagesLoaded} />
      <ProductsSection isLoaded={imagesLoaded} />
      <TheLoop />
    </>
  );
}
