// Main app — composes intro + landing + event pages

const { useState, useEffect, useRef, useCallback } = React;

function useScrollProgress(ref) {
  const [state, setState] = useState({ progress: 0, inIntro: true });
  useEffect(() => {
    const onScroll = () => {
      if (!ref.current) return;
      const rect = ref.current.getBoundingClientRect();
      const total = ref.current.offsetHeight - window.innerHeight;
      const scrolled = -rect.top;
      const p = Math.max(0, Math.min(1, scrolled / total));
      setState({ progress: p, inIntro: scrolled < total && scrolled >= -window.innerHeight * 0.5 });
    };
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll);
    return () => {
      window.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onScroll);
    };
  }, [ref]);
  return state;
}

function isTouchDevice() {
  return (
    typeof window !== 'undefined' &&
    (window.matchMedia('(pointer: coarse)').matches ||
      'ontouchstart' in window ||
      (navigator.maxTouchPoints && navigator.maxTouchPoints > 0))
  );
}

function Intro({ onSkip, onEnded }) {
  const videoRef = useRef(null);
  const containerRef = useRef(null);
  const endedRef = useRef(false);
  const [started, setStarted] = useState(false);
  const [hasScrolled, setHasScrolled] = useState(false);
  const [touchMode] = useState(() => isTouchDevice());

  // Lock body scroll while gate is visible (both modes)
  useEffect(() => {
    if (!started) {
      const orig = document.body.style.overflow;
      document.body.style.overflow = 'hidden';
      return () => { document.body.style.overflow = orig; };
    }
  }, [started]);

  // Scroll-driven scrubbing — DESKTOP only (iOS Safari can't reliably seek video.currentTime)
  useEffect(() => {
    if (!started || touchMode) return;
    const video = videoRef.current;
    const container = containerRef.current;
    if (!video || !container) return;

    let targetTime = 0;
    let displayTime = 0;
    let alive = true;

    const computeTarget = () => {
      const rect = container.getBoundingClientRect();
      const total = container.offsetHeight - window.innerHeight;
      const scrolled = -rect.top;
      const p = total > 0 ? Math.max(0, Math.min(1, scrolled / total)) : 0;
      if (p > 0.005) setHasScrolled(true);
      if (video.duration && !isNaN(video.duration)) {
        targetTime = p * video.duration;
      }
      if (p >= 0.985 && !endedRef.current && onEnded) {
        endedRef.current = true;
        onEnded();
      }
    };

    const tick = () => {
      if (!alive) return;
      displayTime += (targetTime - displayTime) * 0.05;
      if (video.duration && Math.abs(video.currentTime - displayTime) > 0.005) {
        video.currentTime = displayTime;
      }
      requestAnimationFrame(tick);
    };

    const onScroll = () => computeTarget();
    computeTarget();
    displayTime = targetTime;
    requestAnimationFrame(tick);
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll);
    return () => {
      alive = false;
      window.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onScroll);
    };
  }, [started, onEnded, touchMode]);

  const start = () => {
    window.scrollTo(0, 0);
    setStarted(true);
    requestAnimationFrame(async () => {
      const v = videoRef.current;
      if (!v) return;
      try {
        if (touchMode) {
          // Mobile: just play through normally
          await v.play();
        } else {
          // Desktop: prime the video for scroll-scrubbing
          await v.play();
          v.pause();
          v.currentTime = 0;
        }
      } catch (e) {
        try { v.pause(); v.currentTime = 0; } catch(_) {}
      }
    });
  };

  const containerClass = `intro ${touchMode ? 'intro-video' : 'intro-scroll'}${started ? ' started' : ''}`;

  return (
    <div className={containerClass} ref={containerRef}>
      <div className="intro-sticky">
        <video
          ref={videoRef}
          className="intro-canvas"
          src="assets/intro.mp4"
          muted
          autoPlay={false}
          playsInline
          webkit-playsinline="true"
          x5-playsinline="true"
          preload="auto"
          disablePictureInPicture
          tabIndex={-1}
          onEnded={touchMode ? onEnded : undefined}
          style={{ visibility: started ? 'visible' : 'hidden' }}
        />
        {!started && (
          <div className="intro-gate">
            <div className="intro-gate-logo">
              <span>DIGITAL AF<span className="brand-dot">.</span></span>
              <span className="intro-gate-kr">하나됨</span>
            </div>
            <button className="intro-gate-btn" onClick={start}>ENTER →</button>
          </div>
        )}
        {started && (
          <>
            <button className="skip-intro" onClick={onSkip}>SKIP INTRO →</button>
            {!touchMode && !hasScrolled && (
              <div className="intro-scroll-hint">
                <span>SCROLL</span>
                <span className="intro-scroll-arrow">↓</span>
              </div>
            )}
          </>
        )}
      </div>
    </div>
  );
}

function Nav({ active, onNavigate, theme, toggleTheme }) {
  const links = [
    { id: 'home', label: 'HOME' },
    { id: 'contact', label: 'CONTACT' },
  ];
  return (
    <nav className="nav">
      <div className="nav-brand" onClick={() => onNavigate('home')} style={{cursor: 'pointer'}}>
        <span>DIGITAL AF <span className="brand-unity">UNITY</span></span>
      </div>
      <div className="nav-links">
        {links.map(l => (
          <span key={l.id} className={`nav-link ${active === l.id ? 'active' : ''}`} onClick={() => onNavigate(l.id)}>
            {l.label}
          </span>
        ))}
      </div>
      <div className="nav-right">
        <button className="theme-toggle" onClick={toggleTheme}>
          <span className={theme === 'light' ? 'dot-l' : 'dot-d'}/>
          {theme === 'dark' ? 'DARK' : 'LIGHT'}
        </button>
      </div>
    </nav>
  );
}

function CatCursor() {
  const [pos, setPos] = useState({ x: -100, y: -100 });
  useEffect(() => {
    const onMove = (e) => setPos({ x: e.clientX, y: e.clientY });
    window.addEventListener('mousemove', onMove);
    return () => window.removeEventListener('mousemove', onMove);
  }, []);
  return (
    <div className="cat-cursor" style={{ left: pos.x, top: pos.y }}>
      <CatTag size={30} color="#fff"/>
    </div>
  );
}

function ChopsticksCursor() {
  const [pos, setPos] = useState({ x: -100, y: -100 });
  const [closed, setClosed] = useState(false);
  useEffect(() => {
    const onMove = (e) => setPos({ x: e.clientX, y: e.clientY });
    const onDown = () => setClosed(true);
    const onUp = () => setClosed(false);
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mousedown', onDown);
    window.addEventListener('mouseup', onUp);
    return () => {
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mousedown', onDown);
      window.removeEventListener('mouseup', onUp);
    };
  }, []);
  return (
    <div className={`chopsticks-cursor ${closed ? 'closed' : ''}`} style={{ left: pos.x, top: pos.y }}>
      <span className="stick stick-l"/>
      <span className="stick stick-r"/>
    </div>
  );
}

// scatter decorative cats on landing
function ScatterCats() {
  const cats = [
    { x: '5%', y: '120vh', s: 60, rot: -15, wire: false },
    { x: '88%', y: '180vh', s: 80, rot: 20, wire: true },
    { x: '15%', y: '250vh', s: 50, rot: 8, wire: false },
    { x: '75%', y: '320vh', s: 70, rot: -25, wire: true },
    { x: '8%', y: '400vh', s: 90, rot: 12, wire: false },
    { x: '92%', y: '460vh', s: 55, rot: -8, wire: true },
  ];
  return (
    <>
      {cats.map((c, i) => (
        <div key={i} className={`scatter-cat ${c.wire ? 'wireframe-cat' : ''}`} style={{ left: c.x, top: c.y, transform: `rotate(${c.rot}deg)` }}>
          <CatSit size={c.s} color="var(--fg)"/>
        </div>
      ))}
    </>
  );
}

function Main() {
  const [theme, setTheme] = useState(() => localStorage.getItem('daf_theme') || 'dark');
  // Intro plays on every page load. State only persists within the current page session.
  const [introDone, setIntroDone] = useState(false);
  const [tweaksOpen, setTweaksOpen] = useState(false);
  const [cursorCat, setCursorCat] = useState(() => localStorage.getItem('daf_cursor_cat') === '1');
  const [flashing, setFlashing] = useState(false);

  useEffect(() => {
    document.documentElement.setAttribute('data-theme', theme);
    localStorage.setItem('daf_theme', theme);
  }, [theme]);

  // listen for tweak activation
  useEffect(() => {
    const onMsg = (e) => {
      if (!e.data) return;
      if (e.data.type === '__activate_edit_mode') setTweaksOpen(true);
      if (e.data.type === '__deactivate_edit_mode') setTweaksOpen(false);
    };
    window.addEventListener('message', onMsg);
    // announce availability
    requestAnimationFrame(() => {
      try { window.parent.postMessage({type: '__edit_mode_available'}, '*'); } catch(_){}
    });
    return () => window.removeEventListener('message', onMsg);
  }, []);

  const skipIntro = useCallback(() => {
    setIntroDone(true);
    window.scrollTo({ top: 0, behavior: 'instant' });
  }, []);

  const handleIntroEnd = useCallback(() => {
    setFlashing(true);
    // Lock scroll immediately so momentum / trackpad inertia can't carry past
    document.documentElement.style.overflow = 'hidden';
    document.body.style.overflow = 'hidden';
    document.body.style.touchAction = 'none';

    setTimeout(() => {
      sessionStorage.setItem('daf_intro_done', '1');
      setIntroDone(true);
      // wait for React to remove the intro DOM, snap to top of landing,
      // then re-enable scrolling
      requestAnimationFrame(() => {
        requestAnimationFrame(() => {
          window.scrollTo(0, 0);
          document.documentElement.scrollTop = 0;
          document.body.scrollTop = 0;
          requestAnimationFrame(() => {
            document.documentElement.style.overflow = '';
            document.body.style.overflow = '';
            document.body.style.touchAction = '';
          });
        });
      });
    }, 320);
    setTimeout(() => setFlashing(false), 1400);
  }, []);

  const handleNavigate = useCallback((id) => {
    if (id === 'home') {
      window.scrollTo({ top: 0, behavior: 'smooth' });
      return;
    }
    const targetId = id === 'contact' ? 'contact' : `event-${id}`;
    const el = document.getElementById(targetId);
    if (el) {
      const offset = window.innerWidth <= 900 ? 100 : 80;
      window.scrollTo({ top: el.offsetTop - offset, behavior: 'smooth' });
    }
  }, []);

  return (
    <>
      <ChopsticksCursor/>
      {cursorCat && <CatCursor/>}
      {introDone && <Nav active={'home'} onNavigate={handleNavigate} theme={theme} toggleTheme={() => setTheme(t => t === 'dark' ? 'light' : 'dark')}/>}

      {!introDone && <Intro theme={theme} onSkip={skipIntro} onEnded={handleIntroEnd}/>}
      {flashing && <div className="intro-flash"/>}
      {introDone && <div className="glitch-fx" aria-hidden="true"/>}

      <div id="main-landing" style={{position: 'relative'}}>
        <ScatterCats/>
        <Hero theme={theme}/>
        <SiteRedTrail/>
        <ManifestoSection/>
        <TrackRecordSection/>
        <WhatWellDoSection/>
        <SeoulNetworkSection/>
        <VenueSection/>
        <EventsSection/>
        <TimelineSection/>
        <LegacySection/>
        <PartnersSection/>
        <ContactSection/>
      </div>

      {tweaksOpen && (
        <div className="tweaks-panel">
          <h4>TWEAKS</h4>
          <div className="row">
            <span>THEME</span>
            <div style={{display: 'flex', gap: 6}}>
              <button className={`chip ${theme === 'dark' ? 'active' : ''}`} onClick={() => setTheme('dark')}>DARK</button>
              <button className={`chip ${theme === 'light' ? 'active' : ''}`} onClick={() => setTheme('light')}>LIGHT</button>
            </div>
          </div>
          <div className="row">
            <span>CAT CURSOR</span>
            <button className={`chip ${cursorCat ? 'active' : ''}`} onClick={() => { const v = !cursorCat; setCursorCat(v); localStorage.setItem('daf_cursor_cat', v ? '1' : '0'); }}>
              {cursorCat ? 'ON' : 'OFF'}
            </button>
          </div>
          <div className="row">
            <span>INTRO</span>
            <button className="chip" onClick={() => { setIntroDone(false); window.scrollTo(0, 0); }}>REPLAY</button>
          </div>
          <div className="row">
            <span>JUMP TO</span>
            <div style={{display:'flex', gap:4, flexWrap:'wrap'}}>
              {EVENTS.map(e => (
                <button key={e.id} className="chip" onClick={() => handleNavigate(e.id)}>{e.label}</button>
              ))}
            </div>
          </div>
        </div>
      )}
    </>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Main/>);
