/* ============================================================
   CHAI ZEBRA — front-end logic
   ============================================================ */
(() => {
  'use strict';

  /* ---------- DATA: the album track list (from the back cover) ---------- */
  const SONGS = window.CHAI_SONGS;

  /* ---------- DATA: fake social feed (display only) ---------- */
  const POSTS = window.CHAI_POSTS;

  const $  = (s, r=document) => r.querySelector(s);
  const $$ = (s, r=document) => Array.from(r.querySelectorAll(s));

  /* ============================================================
     1. ALBUM — build clickable track list + gatefold open/close
     ============================================================ */
  const tracklist  = $('#tracklist');
  const albumStage = $('#albumStage');

  // Clickable hotspots laid over the printed track list on the inside cover image.
  // Measured off the 1:1 artwork: track 1 starts at 19.42%, ~4.78% apart.
  SONGS.forEach((song, i) => {
    const b = document.createElement('button');
    b.type = 'button';
    b.className = 'hotspot';
    b.dataset.song = song;
    b.title = song;
    b.setAttribute('aria-label', song);
    b.style.top = (19.42 + i * 4.78) + '%';
    b.innerHTML = `<span class="hs-badge" data-faved></span>`;
    b.addEventListener('click', (e) => { e.stopPropagation(); openSongModal(song); });
    tracklist.appendChild(b);
  });

  // Tap the album to open it; while open, tapping anywhere on the spread closes
  // it again — except on a song hotspot (those stopPropagation above and open the
  // fav modal instead, so you can pick tracks without the album snapping shut).
  albumStage.addEventListener('click', () => albumStage.classList.toggle('open'));

  /* ============================================================
     2. SONG FAV MODAL  +  localStorage tracking
     ============================================================ */
  const FAV_KEY = 'chaiZebraFavs';
  const loadFavs = () => { try { return JSON.parse(localStorage.getItem(FAV_KEY)) || {}; } catch { return {}; } };
  const saveFavs = (f) => { try { localStorage.setItem(FAV_KEY, JSON.stringify(f)); } catch {} };
  let favs = loadFavs();

  const songModal = $('#songModal');
  const modalSong = $('#modalSong');
  let currentSong = null;

  function openSongModal(song){
    currentSong = song;
    modalSong.textContent = song;
    songModal.classList.add('show');
    document.body.style.overflow = 'hidden';
  }
  function closeSongModal(){
    songModal.classList.remove('show');
    document.body.style.overflow = '';
  }

  $('#modalClose').addEventListener('click', closeSongModal);
  $('#favNo').addEventListener('click', closeSongModal);
  songModal.addEventListener('click', (e) => { if (e.target === songModal) closeSongModal(); });
  document.addEventListener('keydown', (e) => { if (e.key === 'Escape') closeSongModal(); });

  $('#favYes').addEventListener('click', () => {
    if (!currentSong) return;
    favs[currentSong] = (favs[currentSong] || 0) + 1;
    saveFavs(favs);
    markFaved(currentSong);
    closeSongModal();
  });

  function markFaved(song){
    const hs = $$('#tracklist .hotspot').find(el => el.dataset.song === song);
    if (hs){
      const badge = hs.querySelector('[data-faved]');
      badge.textContent = `★${favs[song]}`;
      badge.classList.add('on');
    }
  }
  // restore any faved badges from a previous visit
  Object.keys(favs).forEach(markFaved);

  /* ============================================================
     3. SOCIAL FEED — render posts (doubled for seamless loop)
     ============================================================ */
  const feedColumn  = $('#feedColumn');
  const feedStories = $('#feedStories');
  const EMOJIS = ['🦓','🔥','👑','🖤','✨','🎤','🎶','😭'];

  const fmt = (n) => n >= 1000 ? (n/1000).toFixed(1).replace('.0','') + 'k' : '' + n;
  const linkTags = (txt) => txt.replace(/#(\w+)/g, '<span class="tag">#$1</span>');

  function postNode(p){
    const el = document.createElement('article');
    el.className = 'post';
    el.innerHTML = `
      <div class="post-top">
        <div class="post-av" style="background:${p.c}">${p.u[0]}</div>
        <div class="post-id">
          <span class="post-name">${p.u}${p.v ? '<span class="verified">✔</span>' : ''}</span>
          <span class="post-handle">@${p.h}</span>
        </div>
        <span class="post-time">${p.t}</span>
      </div>
      <p class="post-text">${linkTags(p.text)}</p>
      <div class="post-actions">
        <button class="like" type="button"><span class="heart">🤍</span> <span class="n">${fmt(p.likes)}</span></button>
        <button type="button">💬 ${fmt(p.cm)}</button>
        <button type="button">🔁 ${fmt(Math.round(p.likes/9))}</button>
        <button type="button">↗</button>
      </div>`;
    el.querySelector('.like').addEventListener('click', function(){
      const heart = this.querySelector('.heart');
      const n = this.querySelector('.n');
      if (this.classList.toggle('liked')){
        heart.textContent = '🧡'; n.textContent = fmt(p.likes + 1);
      } else {
        heart.textContent = '🤍'; n.textContent = fmt(p.likes);
      }
    });
    return el;
  }

  // doubled list => the -50% keyframe loops seamlessly
  [...POSTS, ...POSTS].forEach(p => feedColumn.appendChild(postNode(p)));

  // stories rail
  POSTS.slice(0, 10).forEach((p, i) => {
    const s = document.createElement('div');
    s.className = 'story';
    s.innerHTML = `<div class="story-ring"><div class="story-av">${EMOJIS[i % EMOJIS.length]}</div></div><span>${p.h}</span>`;
    feedStories.appendChild(s);
  });

  /* ============================================================
     5. SUBSCRIBE — exploding Chai splash
     ============================================================ */
  const splash = $('#splash');
  $('#subForm').addEventListener('submit', (e) => {
    e.preventDefault();
    // record the new fan so the Console's Fan Tracker picks them up
    const name = ($('#subName') && $('#subName').value || '').trim();
    const email = ($('#subEmail') && $('#subEmail').value || '').trim();
    if (window.CHAI_FANS && email){
      window.CHAI_FANS.add({
        id: window.CHAI_FANS.newId(), name, email, x: '',
        added: window.CHAI_FANS.todayISO(),
        labels: { great: false, super: false, concerning: false },
      });
    }
    splash.classList.add('show');
    document.body.style.overflow = 'hidden';
    // re-trigger the staggered word animations each time
    $$('#splashWords .sw').forEach(w => {
      w.style.animation = 'none';
      void w.offsetWidth;            // force reflow
      w.style.animation = '';
    });
  });

  // each splash word dances when clicked
  $$('#splashWords .sw').forEach(w => {
    w.addEventListener('click', () => {
      w.classList.remove('dance');
      void w.offsetWidth;
      w.classList.add('dance');
    });
  });

  $('#splashHome').addEventListener('click', () => {
    splash.classList.remove('show');
    document.body.style.overflow = '';
    document.getElementById('top').scrollIntoView({ behavior:'smooth' });
  });

  /* ============================================================
     5b. TOUR — live dates + ticket toast
     ============================================================ */
  const TOUR = [
    { mon:'JUN', day:'27', city:'Brooklyn, NY',    venue:'Zebra Hall',                status:'few' },
    { mon:'JUL', day:'03', city:'Atlanta, GA',     venue:'The Watering Hole',         status:'on'  },
    { mon:'JUL', day:'11', city:'Chicago, IL',     venue:'Savanna Room',              status:'out' },
    { mon:'JUL', day:'19', city:'Austin, TX',      venue:'Stripe City Amphitheater',  status:'on'  },
    { mon:'JUL', day:'26', city:'Denver, CO',      venue:'The Mane Stage',            status:'few' },
    { mon:'AUG', day:'02', city:'Los Angeles, CA', venue:'Jungle Arena',              status:'on'  },
    { mon:'AUG', day:'09', city:'Seattle, WA',     venue:'Hooves & Harmony',          status:'on'  },
    { mon:'AUG', day:'16', city:'Vancouver, BC',   venue:'The Herd House',            status:'out' },
  ];
  const STATUS = { on:['ON SALE','Get Tickets'], few:['FEW LEFT','Get Tickets'], out:['SOLD OUT','Sold Out'] };
  const tourList = $('#tourList');

  // toast
  const toastEl = document.createElement('div');
  toastEl.className = 'toast';
  document.body.appendChild(toastEl);
  let toastTimer;
  function toast(msg){
    toastEl.textContent = msg;
    toastEl.classList.add('show');
    clearTimeout(toastTimer);
    toastTimer = setTimeout(() => toastEl.classList.remove('show'), 3200);
  }

  TOUR.forEach((t, i) => {
    const [label, btnText] = STATUS[t.status];
    const row = document.createElement('div');
    row.className = 'tour-row reveal';
    row.style.transitionDelay = (i * 0.05) + 's';
    row.innerHTML = `
      <div class="tour-date"><span class="mon">${t.mon}</span><span class="day">${t.day}</span></div>
      <div class="tour-info"><div class="city">${t.city}</div><div class="venue">${t.venue}</div></div>
      <span class="tour-status ${t.status}">${label}</span>
      <button class="tour-btn" ${t.status === 'out' ? 'disabled' : ''}>${btnText}</button>`;
    if (t.status !== 'out'){
      row.querySelector('.tour-btn').addEventListener('click', () =>
        toast(`🎟️ You're on the list for ${t.city.split(',')[0]}! (demo)`));
    }
    tourList.appendChild(row);
  });

  /* ============================================================
     6. Reveal-on-scroll
     ============================================================ */
  const io = new IntersectionObserver((entries) => {
    entries.forEach(en => { if (en.isIntersecting){ en.target.classList.add('in'); io.unobserve(en.target); } });
  }, { threshold:.12 });
  $$('.section-head, .panel, .sub-card, .album-stage, .feed-wrap, .tour-row').forEach(el => {
    el.classList.add('reveal'); io.observe(el);
  });

  /* ============================================================
     7. Nav background solidifies once you scroll off the hero
     ============================================================ */
  const nav = document.getElementById('top');
  const onScroll = () => nav.classList.toggle('scrolled', window.scrollY > 40);
  window.addEventListener('scroll', onScroll, { passive:true });
  onScroll();

  /* ---------- mobile hamburger menu ---------- */
  const navBurger = $('#navBurger');
  const navMenu = $('#navMenu');
  if (navBurger && navMenu){
    const closeMenu = () => {
      navMenu.classList.remove('open');
      navBurger.classList.remove('open');
      navBurger.setAttribute('aria-expanded', 'false');
      navMenu.setAttribute('aria-hidden', 'true');
    };
    navBurger.addEventListener('click', (e) => {
      e.stopPropagation();
      const open = !navMenu.classList.contains('open');
      navMenu.classList.toggle('open', open);
      navBurger.classList.toggle('open', open);
      navBurger.setAttribute('aria-expanded', open ? 'true' : 'false');
      navMenu.setAttribute('aria-hidden', open ? 'false' : 'true');
      if (open) navMenu.style.top = nav.offsetHeight + 'px';   // drop below the header bar
    });
    navMenu.addEventListener('click', (e) => { if (e.target.tagName === 'A') closeMenu(); });
    document.addEventListener('click', (e) => { if (!navMenu.contains(e.target) && !navBurger.contains(e.target)) closeMenu(); });
    document.addEventListener('keydown', (e) => { if (e.key === 'Escape') closeMenu(); });
    window.addEventListener('resize', closeMenu);
  }

  /* ============================================================
     7b. HERO — negative torch (inverted colours under the cursor)
         + logo "stamp" that only lights when the cursor is over it
     ============================================================ */
  const heroEl = document.querySelector('.hero');
  const heroMark = document.querySelector('.hero-mark');
  if (heroEl && document.querySelector('.hero-invert')){
    let mx = -300, my = -300, raf = null;
    const apply = () => {
      heroEl.style.setProperty('--mx', mx + 'px');
      heroEl.style.setProperty('--my', my + 'px');
      raf = null;
    };
    heroEl.addEventListener('pointermove', (e) => {
      if (e.pointerType === 'touch') return;
      const r = heroEl.getBoundingClientRect();
      mx = e.clientX - r.left; my = e.clientY - r.top;
      heroEl.classList.add('torch-on');
      if (!raf) raf = requestAnimationFrame(apply);
      if (heroMark){                                    // logo lights only while pointer is over its box
        const m = heroMark.getBoundingClientRect();
        const over = e.clientX >= m.left && e.clientX <= m.right && e.clientY >= m.top && e.clientY <= m.bottom;
        heroMark.classList.toggle('lit', over);
      }
    });
    heroEl.addEventListener('pointerleave', () => {
      heroEl.classList.remove('torch-on');
      if (heroMark) heroMark.classList.remove('lit');
    });
  }

  /* ============================================================
     8. AUDIO — teaser montage + bouncing boombox now-playing
     ============================================================ */
  const AUDIO_SRC = {
    'A Revolution ft. Goala Girls': 'Songs/A-Revolution__cz-gg.mp3',
    'Never Wanted to be Queen':      'Songs/Never-Wanted-to%20be-Queen__cz.mp3',
  };
  const NWQ = AUDIO_SRC['Never Wanted to be Queen'];

  const audio = new Audio();
  audio.preload = 'metadata';
  audio.src = NWQ;                        // preload teaser track so seeking is ready on first click
  document.body.appendChild(audio);
  let mode = 'idle', teaserTimer = null, fadeTimer = null, activePlay = null, curSrc = NWQ;

  const teaserBtn   = $('#teaserBtn');
  const teaserLabel = $('.teaser-label', teaserBtn);
  const bbPlayer = $('#bbPlayer'), bbTitle = $('#bbTitle'), bbNow = $('#bbNow'),
        bbProgress = $('#bbProgress'), bbEq = $('#bbEq');

  // boombox EQ bars (varied, so the visualizer looks alive)
  for (let k = 0; k < 15; k++){
    const b = document.createElement('i');
    b.style.animationDuration = (0.42 + Math.random() * 0.5).toFixed(2) + 's';
    b.style.animationDelay = (-Math.random()).toFixed(2) + 's';
    bbEq.appendChild(b);
  }

  function stopAudio(){
    clearTimeout(teaserTimer); teaserTimer = null;
    clearInterval(fadeTimer); fadeTimer = null;
    try { audio.pause(); } catch {}
    audio.volume = 1;
    mode = 'idle';
    teaserBtn.classList.remove('playing'); teaserLabel.textContent = '▶ Play Teaser';
    $$('.track-play.playing').forEach(b => b.classList.remove('playing'));
    activePlay = null;
  }
  const setSrc = (src) => { if (curSrc !== src){ audio.src = src; curSrc = src; } };
  const showBoombox = (title, status) => {
    bbTitle.textContent = title;
    if (bbNow) bbNow.textContent = '▶ ' + status;
    bbPlayer.classList.add('show');
  };
  const hideBoombox = () => bbPlayer.classList.remove('show');

  // play() is always kicked off inside the click gesture; surface (not swallow) failures
  function safePlay(){
    const p = audio.play();
    if (p && p.catch) p.catch(err => {
      console.warn('[chai audio] play blocked:', err && err.name, err && err.message);
      if (typeof toast === 'function') toast('🔊 Tap play once more to start the audio');
    });
  }
  // smoothly ramp audio.volume to target over `dur` seconds, then run `done`
  function fadeTo(target, dur, done){
    clearInterval(fadeTimer);
    const startV = audio.volume, steps = Math.max(1, Math.round(dur / 0.05));
    let n = 0;
    fadeTimer = setInterval(() => {
      n++;
      audio.volume = Math.min(1, Math.max(0, startV + (target - startV) * (n / steps)));
      if (n >= steps){ clearInterval(fadeTimer); fadeTimer = null; if (done) done(); }
    }, 50);
  }

  // --- full song -> bouncing boombox ---
  function playSong(src, title, btn){
    if (mode === 'song' && activePlay === btn){ stopAudio(); hideBoombox(); return; }  // toggle off
    stopAudio();
    mode = 'song'; setSrc(src); audio.muted = false; audio.currentTime = 0;
    safePlay();                                          // synchronous within the click
    showBoombox(title, 'NOW PLAYING');
    if (btn){ btn.classList.add('playing'); activePlay = btn; }
  }
  audio.addEventListener('timeupdate', () => {
    if (mode === 'song' && audio.duration) bbProgress.style.width = (audio.currentTime / audio.duration * 100) + '%';
  });
  audio.addEventListener('ended', () => { if (mode === 'song'){ stopAudio(); hideBoombox(); } });
  $('#bbClose').addEventListener('click', () => { stopAudio(); hideBoombox(); });

  // inject play buttons over the inside-cover tracks that have audio
  const playsLayer = document.createElement('div');
  playsLayer.className = 'track-plays';
  tracklist.parentElement.appendChild(playsLayer);
  SONGS.forEach((song, i) => {
    const src = AUDIO_SRC[song]; if (!src) return;
    const pb = document.createElement('button');
    pb.type = 'button'; pb.className = 'track-play'; pb.textContent = '▶ PLAY'; pb.title = 'Play ' + song;
    pb.style.top = (25.8 + i * 4.78) + '%'; pb.style.left = '41%';   // a bit below the track centre
    pb.addEventListener('click', (e) => { e.stopPropagation(); playSong(src, song, pb); });
    playsLayer.appendChild(pb);
  });

  // --- teaser: 5 distinct, non-overlapping 3s clips of Never Wanted to be Queen ---
  function pickSegments(n, len, lo, hi){
    const segs = []; let guard = 0;
    while (segs.length < n && guard++ < 800){
      const s = Math.round(lo + Math.random() * (hi - lo - len));
      if (segs.every(x => Math.abs(x - s) >= len + 0.5)) segs.push(s);   // no overlap => never the same part twice
    }
    return segs;
  }
  function playTeaser(){
    if (mode === 'teaser'){ stopAudio(); hideBoombox(); return; }         // toggle off
    stopAudio();
    mode = 'teaser'; setSrc(NWQ); audio.muted = false;
    teaserBtn.classList.add('playing');
    showBoombox('Never Wanted to be Queen', 'TEASER · 1/5');              // boombox bounces during the teaser too
    const CLIP = 8, FADE = 0.7;                                          // 8s per clip, 0.7s fades
    const segs = pickSegments(5, CLIP, 6, 170); let i = 0;
    const playSeg = () => {
      if (mode !== 'teaser') return;
      if (i >= segs.length){ stopAudio(); hideBoombox(); return; }
      if (bbNow) bbNow.textContent = '▶ TEASER · ' + (i + 1) + '/5';
      bbProgress.style.width = ((i + 1) / 5 * 100) + '%';
      try { audio.currentTime = segs[i]; } catch {}
      audio.volume = 0; safePlay(); fadeTo(1, FADE);                     // fade the clip in
      teaserTimer = setTimeout(() => {
        fadeTo(0, FADE, () => { i++; playSeg(); });                      // fade out, then the next clip
      }, (CLIP - FADE) * 1000);
    };
    if (audio.readyState >= 1) playSeg();                                 // metadata preloaded -> seek+play in-gesture
    else { audio.muted = true; safePlay(); audio.addEventListener('canplay', () => { audio.muted = false; if (mode === 'teaser') playSeg(); }, { once:true }); }
  }
  teaserBtn.addEventListener('click', playTeaser);

})();
