// Seasonal imagery, ambient audio, cursor-reactive parallax, video hero.
// All features are additive — degrades gracefully without JS.

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

// ─── Season-specific imagery bank
// Each season has its own hero video, hero-right still, ambient bands, program bgs.
// Videos: Coverr / Pexels CC-licensed nature loops (transcoded to mp4).
// If you have custom brand video later, swap the urls in SEASONS.
const SEASONS = {
  spring: {
    label: 'Spring',
    accent: '#A8B87A',
    glow: 'rgba(168, 184, 122, 0.12)',
    // Spring: Ken Burns still (video unreliable for vibrant spring foliage) — lush meadow with wildflowers
    heroVideo: null,
    heroPoster: 'https://images.unsplash.com/photo-1490750967868-88aa4486c946?w=1800&q=80&auto=format&fit=crop',
    heroRight: 'https://images.unsplash.com/photo-1465146344425-f00d5f5c8f07?w=1400&q=80&auto=format&fit=crop',
    band1: 'https://images.unsplash.com/photo-1490750967868-88aa4486c946?w=1800&q=80&auto=format&fit=crop',
    band2: 'https://images.unsplash.com/photo-1501854140801-50d01698950b?w=1800&q=80&auto=format&fit=crop',
    finalCta: 'https://images.unsplash.com/photo-1438565434616-3ef039228b15?w=1800&q=80&auto=format&fit=crop',
    heroEyebrow: 'NH · VT · MA · CT · NE · NY · MD',
    heroCaption: 'Spring 2026',
  },
  summer: {
    label: 'Summer',
    accent: '#C9A875',
    glow: 'rgba(201, 168, 117, 0.10)',
    heroVideo: 'https://assets.mixkit.co/videos/529/529-720.mp4',
    heroPoster: 'https://images.unsplash.com/photo-1441974231531-c6227db76b6e?w=1800&q=80&auto=format&fit=crop',
    heroRight: 'https://images.unsplash.com/photo-1511497584788-876760111969?w=1400&q=80&auto=format&fit=crop',
    band1: 'https://images.unsplash.com/photo-1518495973542-4542c06a5843?w=1800&q=80&auto=format&fit=crop',
    band2: 'https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?w=1800&q=80&auto=format&fit=crop',
    finalCta: 'https://images.unsplash.com/photo-1483728642387-6c3bdd6c93e5?w=1800&q=80&auto=format&fit=crop',
    heroEyebrow: 'NH · VT · MA · CT · NE · NY · MD',
    heroCaption: 'Summer 2026',
  },
  autumn: {
    label: 'Autumn',
    accent: '#D49261',
    glow: 'rgba(212, 146, 97, 0.12)',
    // Autumn: Ken Burns still of peak NE foliage — vibrant red/orange/yellow canopy
    heroVideo: null,
    heroPoster: 'https://images.unsplash.com/photo-1507783548227-544c3b8fc065?w=1800&q=80&auto=format&fit=crop',
    heroRight: 'https://images.unsplash.com/photo-1506126613408-eca07ce68773?w=1400&q=80&auto=format&fit=crop',
    band1: 'https://images.unsplash.com/photo-1507041957456-9c397ce39c97?w=1800&q=80&auto=format&fit=crop',
    band2: 'https://images.unsplash.com/photo-1472214103451-9374bd1c798e?w=1800&q=80&auto=format&fit=crop',
    finalCta: 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=1800&q=80&auto=format&fit=crop',
    heroEyebrow: 'NH · VT · MA · CT · NE · NY · MD',
    heroCaption: 'Autumn 2026',
  },
  winter: {
    label: 'Winter',
    accent: '#B8C4D4',
    glow: 'rgba(184, 196, 212, 0.10)',
    heroVideo: 'https://assets.mixkit.co/videos/1172/1172-720.mp4',
    heroPoster: 'https://images.unsplash.com/photo-1418985991508-e47386d96a71?w=1800&q=80&auto=format&fit=crop',
    heroRight: 'https://images.unsplash.com/photo-1482192505345-5655af888cc4?w=1400&q=80&auto=format&fit=crop',
    band1: 'https://images.unsplash.com/photo-1483921020237-2ff51e8e4b22?w=1800&q=80&auto=format&fit=crop',
    band2: 'https://images.unsplash.com/photo-1418985991508-e47386d96a71?w=1800&q=80&auto=format&fit=crop',
    finalCta: 'https://images.unsplash.com/photo-1491002052546-bf38f186af56?w=1800&q=80&auto=format&fit=crop',
    heroEyebrow: 'NH · VT · MA · CT · NE · NY · MD',
    heroCaption: 'Winter 2026',
  },
};

// Auto-detect season from current month (Northern Hemisphere).
const autoSeason = () => {
  const m = new Date().getMonth(); // 0..11
  if (m >= 2 && m <= 4) return 'spring';
  if (m >= 5 && m <= 7) return 'summer';
  if (m >= 8 && m <= 10) return 'autumn';
  return 'winter';
};

// ─── Season context: drives --season-accent variable and imagery bank.
function useSeasonEffect(season) {
  useEffect(() => {
    const s = SEASONS[season] || SEASONS.summer;
    document.documentElement.style.setProperty('--season-accent', s.accent);
    document.documentElement.style.setProperty('--season-glow', s.glow);
    document.documentElement.setAttribute('data-season', season);
  }, [season]);
}

// ─── Cursor-reactive tilt: subtle mouse-follow transform on a target element.
// Keep subtle (4–8deg max) to avoid motion sickness.
function useCursorTilt(ref, { max = 6, scale = 1.04 } = {}) {
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;

    let raf = null;
    let tx = 0, ty = 0, targetX = 0, targetY = 0;
    const onMove = (e) => {
      const r = el.getBoundingClientRect();
      const cx = r.left + r.width / 2;
      const cy = r.top + r.height / 2;
      targetX = ((e.clientX - cx) / (r.width / 2)) * max;
      targetY = ((e.clientY - cy) / (r.height / 2)) * max;
      schedule();
    };
    const onLeave = () => { targetX = 0; targetY = 0; schedule(); };
    const schedule = () => {
      if (raf) return;
      raf = requestAnimationFrame(tick);
    };
    const tick = () => {
      tx += (targetX - tx) * 0.08;
      ty += (targetY - ty) * 0.08;
      el.style.transform = `perspective(1200px) rotateY(${tx}deg) rotateX(${-ty}deg) scale(${scale})`;
      if (Math.abs(tx - targetX) > 0.05 || Math.abs(ty - targetY) > 0.05) {
        raf = requestAnimationFrame(tick);
      } else {
        raf = null;
      }
    };
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseout', onLeave);
    return () => {
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mouseout', onLeave);
      if (raf) cancelAnimationFrame(raf);
      if (el) el.style.transform = '';
    };
  }, [ref, max, scale]);
}

// ─── Ambient audio: forest/stream ASMR loop. Off by default, user-toggle only.
// Per Chrome autoplay policy, audio requires user gesture — we only start on click.
const AudioToggle = ({ src = 'https://cdn.pixabay.com/download/audio/2022/03/15/audio_8a6d62be03.mp3', label = 'Ambient' }) => {
  const [on, setOn] = useState(false);
  const [ready, setReady] = useState(false);
  const audioRef = useRef(null);

  useEffect(() => {
    if (!audioRef.current) {
      const a = new Audio(src);
      a.loop = true;
      a.volume = 0;
      a.preload = 'none';
      audioRef.current = a;
      a.addEventListener('canplay', () => setReady(true));
      a.addEventListener('error', () => setReady(false));
    }
    return () => {
      if (audioRef.current) {
        try { audioRef.current.pause(); } catch(e) {}
      }
    };
  }, [src]);

  const toggle = async () => {
    const a = audioRef.current;
    if (!a) return;
    if (on) {
      fadeVol(a, 0, 600, () => { try { a.pause(); } catch(e) {} });
      setOn(false);
    } else {
      try {
        a.currentTime = a.currentTime || 0;
        await a.play();
        fadeVol(a, 0.35, 1400);
        setOn(true);
      } catch (err) {
        console.warn('audio play failed', err);
      }
    }
  };

  return (
    <button className={`audio-toggle ${on ? 'on' : ''}`} onClick={toggle} aria-label="Toggle ambient audio" title={on ? 'Pause ambient audio' : 'Play ambient audio'}>
      <span className="audio-bars" aria-hidden="true">
        <span /><span /><span /><span />
      </span>
      <span className="audio-label">{on ? 'Playing' : label}</span>
    </button>
  );
};

function fadeVol(audio, target, ms, done) {
  const start = audio.volume;
  const t0 = performance.now();
  const step = (now) => {
    const t = Math.min(1, (now - t0) / ms);
    audio.volume = start + (target - start) * t;
    if (t < 1) requestAnimationFrame(step);
    else if (done) done();
  };
  requestAnimationFrame(step);
}

// ─── HeroVideo: auto-playing looping nature video with poster fallback.
// Uses muted+playsInline for autoplay; respects reduced-motion (shows poster only).
const HeroVideo = ({ src, poster, opacity = 0.55 }) => {
  const ref = useRef(null);
  const [loaded, setLoaded] = useState(false);
  const [failed, setFailed] = useState(false);
  const reducedMotion = typeof window !== 'undefined' && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

  useEffect(() => {
    const v = ref.current;
    if (!v || reducedMotion) return;
    const onCanPlay = () => setLoaded(true);
    const onErr = () => setFailed(true);
    v.addEventListener('canplay', onCanPlay);
    v.addEventListener('error', onErr);
    // Force-play in case autoplay is blocked but muted
    v.play().catch(() => {});
    return () => {
      v.removeEventListener('canplay', onCanPlay);
      v.removeEventListener('error', onErr);
    };
  }, [src, reducedMotion]);

  return (
    <div className="hero-video-wrap" aria-hidden="true">
      <div
        className="hero-video-poster"
        style={{ backgroundImage: `url(${poster})`, opacity: opacity }}
      />
      {!reducedMotion && !failed && (
        <video
          ref={ref}
          className={`hero-video ${loaded ? 'loaded' : ''}`}
          src={src}
          poster={poster}
          autoPlay
          loop
          muted
          playsInline
          preload="auto"
          style={{ opacity: loaded ? opacity : 0 }}
        />
      )}
    </div>
  );
};

Object.assign(window, {
  SEASONS,
  autoSeason,
  useSeasonEffect,
  useCursorTilt,
  AudioToggle,
  HeroVideo,
});
