// Wander — Active tour player with real audio support

function PlayerScreen({ tourId, onBack, onComplete, dense }) {
  const { TOURS, stopsForTour } = window.WANDER_DATA;
  const tour = TOURS.find(t => t.id===tourId) || TOURS[0];
  const STOPS = stopsForTour(tour.id);
  const [playing, setPlaying] = React.useState(false);
  const [stopIdx, setStopIdx] = React.useState(0);
  const stop = STOPS[stopIdx];
  const [progress, setProgress] = React.useState(0);
  const [tab, setTab] = React.useState('story');
  const audioRef = React.useRef(null);

  // ── Live location: drive auto-advance by physically arriving at a stop ───────
  const ARRIVE_M = 45; // geofence radius
  const [geo, setGeo] = React.useState(() => (window.WanderGeo ? window.WanderGeo.get() : null));
  const [nudge, setNudge] = React.useState(null); // {name, n} when you reach a stop
  const arrivedRef = React.useRef(0);             // highest stop index already reached

  // Point the location service at THIS tour's route (sim walks it off-site).
  React.useEffect(() => {
    const g = window.WanderGeo;
    if (!g) return;
    const route = STOPS.filter(s => s.lat != null).map(s => ({ lat: s.lat, lng: s.lng }));
    g.ensure({ route, dwell: 8000, speed: 10, loop: false });
    return g.subscribe(setGeo);
  }, [tour.id]);

  // Manual skips shouldn't let geofencing re-trigger an already-passed stop.
  React.useEffect(() => { if (stopIdx > arrivedRef.current) arrivedRef.current = stopIdx; }, [stopIdx]);

  // Geofence: when you walk within range of the next unvisited stop, advance to
  // it and start its narration automatically.
  React.useEffect(() => {
    if (!geo || !geo.coords) return;
    for (let j = arrivedRef.current + 1; j < STOPS.length; j++) {
      const s = STOPS[j];
      if (s.lat == null) continue;
      if (geo.distance(geo.coords, { lat: s.lat, lng: s.lng }) <= ARRIVE_M) {
        arrivedRef.current = j;
        setStopIdx(j);
        setPlaying(true);
        setNudge({ name: s.name, n: j + 1 });
        break;
      }
    }
  }, [geo]);

  // Auto-dismiss the arrival nudge.
  React.useEffect(() => {
    if (!nudge) return;
    const t = setTimeout(() => setNudge(null), 4200);
    return () => clearTimeout(t);
  }, [nudge]);

  const nextStop = STOPS[stopIdx + 1];
  const distToNext = (geo && geo.coords && nextStop && nextStop.lat != null)
    ? geo.distance(geo.coords, { lat: nextStop.lat, lng: nextStop.lng }) : null;
  const distToCurrent = (geo && geo.coords && stop.lat != null)
    ? geo.distance(geo.coords, { lat: stop.lat, lng: stop.lng }) : null;
  const atCurrent = distToCurrent != null && distToCurrent <= ARRIVE_M;

  // Text-to-speech narration (used when no recorded audio file is attached)
  const synthRef  = React.useRef(typeof window !== 'undefined' ? window.speechSynthesis : null);
  const utterRef  = React.useRef(null);
  const spokenIdxRef = React.useRef(-1);
  const ttsActive = !tour.audio_url && !!synthRef.current && !!stop.narration;

  const speakCurrent = React.useCallback(() => {
    const synth = synthRef.current;
    if (!synth || !stop.narration) return;
    const text = stop.narration;
    const u = new SpeechSynthesisUtterance(text);
    u.rate = 0.95; u.pitch = 1.0;
    const voices = synth.getVoices ? synth.getVoices() : [];
    const pref = voices.find(v => /en[-_]GB/i.test(v.lang)) || voices.find(v => /^en/i.test(v.lang));
    if (pref) u.voice = pref;
    u.onboundary = (e) => {
      if (e.charIndex != null) setProgress(Math.min(1, e.charIndex / text.length));
    };
    u.onend = () => {
      if (utterRef.current !== u) return; // ignore cancelled/superseded utterances
      setProgress(1);
      setPlaying(false);
    };
    utterRef.current = u;
    spokenIdxRef.current = stopIdx;
    setProgress(0);
    synth.cancel();
    synth.speak(u);
  }, [stop.narration, stopIdx]);

  // Drive narration playback via the Web Speech API
  React.useEffect(() => {
    if (!ttsActive) return;
    const synth = synthRef.current;
    if (playing) {
      if (synth.paused && spokenIdxRef.current === stopIdx) synth.resume();
      else speakCurrent();
    } else if (synth.speaking) {
      synth.pause();
    }
  }, [playing, stopIdx, ttsActive, speakCurrent]);

  // Stop any narration when leaving the player
  React.useEffect(() => () => { if (synthRef.current) synthRef.current.cancel(); }, []);

  // Reset the progress bar whenever the stop changes
  React.useEffect(() => { setProgress(0); }, [stopIdx]);

  // Keep-alive: Chrome silently cuts off long utterances after ~15s; nudge it.
  React.useEffect(() => {
    if (!ttsActive || !playing) return;
    const id = setInterval(() => {
      const synth = synthRef.current;
      if (synth && synth.speaking && !synth.paused) { synth.pause(); synth.resume(); }
    }, 10000);
    return () => clearInterval(id);
  }, [ttsActive, playing]);

  // Simulated progress only when there's neither a recorded file nor speech
  React.useEffect(() => {
    if (tour.audio_url || ttsActive) return;
    if (!playing) return;
    const id = setInterval(() => setProgress(p => p>=1 ? 0 : Math.min(1, p+0.004)), 100);
    return () => clearInterval(id);
  }, [playing, tour.audio_url, ttsActive]);

  // Sync real audio
  React.useEffect(() => {
    const el = audioRef.current;
    if (!el) return;
    if (playing) el.play().catch(()=>{});
    else el.pause();
  }, [playing]);

  const handleAudioTimeUpdate = (e) => {
    const el = e.target;
    if (el.duration) setProgress(el.currentTime / el.duration);
  };

  return (
    <div style={{ height:'100%', overflow:'hidden', position:'relative', background:`linear-gradient(180deg,${tour.hero[0]} 0%,${tour.hero[1]} 50%,var(--w-ink) 100%)` }}>
      {/* Hidden real audio element */}
      {tour.audio_url && (
        <audio ref={audioRef} src={tour.audio_url} onTimeUpdate={handleAudioTimeUpdate} onEnded={()=>setPlaying(false)} style={{ display:'none' }}/>
      )}

      {/* Top bar */}
      <div style={{ position:'absolute', top:56, left:16, right:16, zIndex:30, display:'flex', alignItems:'center', gap:12 }}>
        <button onClick={onBack} style={{ width:42, height:42, borderRadius:21, background:'rgba(0,0,0,0.25)', backdropFilter:'blur(10px)', border:'none', cursor:'pointer', color:'#fff', display:'flex', alignItems:'center', justifyContent:'center' }}><Icon.back size={18} color="#fff"/></button>
        <div style={{ flex:1, textAlign:'center', color:'#fff' }}>
          <div style={{ fontSize:11, opacity:0.85, fontWeight:600, letterSpacing:0.5, textTransform:'uppercase' }}>Now Playing</div>
          <div style={{ fontWeight:700, fontSize:14, marginTop:1 }}>{tour.title}</div>
        </div>
        <button onClick={onComplete} style={{ height:42, padding:'0 14px', borderRadius:21, background:'rgba(0,0,0,0.25)', backdropFilter:'blur(10px)', border:'none', cursor:'pointer', color:'#fff', fontWeight:700, fontSize:13, fontFamily:'inherit' }}>End</button>
      </div>

      {/* Arrival nudge — fires when you physically reach a stop */}
      {nudge && (
        <div style={{ position:'absolute', top:150, left:'50%', transform:'translateX(-50%)', zIndex:40, background:'rgba(45,212,167,0.96)', color:'#06291F', padding:'12px 18px', borderRadius:18, boxShadow:'0 10px 30px rgba(0,0,0,0.3)', display:'flex', alignItems:'center', gap:10, animation:'wFadeUp .4s ease-out both', maxWidth:320 }}>
          <span style={{ fontSize:22 }}>📍</span>
          <div>
            <div style={{ fontWeight:800, fontSize:13 }}>You've reached stop {nudge.n}</div>
            <div style={{ fontSize:12.5, fontWeight:600 }}>{nudge.name} — playing now</div>
          </div>
        </div>
      )}

      {/* Stop progress dots */}
      <div style={{ position:'absolute', top:110, left:22, right:22, zIndex:20, display:'flex', gap:4 }}>
        {STOPS.map((s,i) => (
          <div key={s.id} style={{ flex:1, height:4, borderRadius:2, background:i<stopIdx?'#fff':i===stopIdx?'rgba(255,255,255,0.8)':'rgba(255,255,255,0.25)', position:'relative', overflow:'hidden' }}>
            {i===stopIdx && <div style={{ position:'absolute', inset:0, width:progress*100+'%', background:'#fff' }}/>}
          </div>
        ))}
      </div>

      {/* Album art */}
      <div style={{ position:'absolute', top:140, left:0, right:0, height:280, display:'flex', alignItems:'center', justifyContent:'center' }}>
        <div style={{ width:240, height:240, borderRadius:40, background:`linear-gradient(135deg,${tour.hero[0]},${tour.hero[1]})`, boxShadow:'0 24px 60px rgba(0,0,0,0.35),inset 0 0 0 6px rgba(255,255,255,0.18)', display:'flex', alignItems:'center', justifyContent:'center', position:'relative', overflow:'hidden', animation:playing?'wFloat 4s ease-in-out infinite':'none' }}>
          <div style={{ position:'absolute', top:-30, right:-40, width:160, height:160, borderRadius:'50%', background:'rgba(255,255,255,0.18)' }}/>
          <div style={{ position:'absolute', bottom:-40, left:-30, width:130, height:130, borderRadius:'50%', background:'rgba(0,0,0,0.12)' }}/>
          <div style={{ fontSize:110, filter:'drop-shadow(0 8px 20px rgba(0,0,0,0.25))', position:'relative', zIndex:1 }}>{tour.emoji}</div>
        </div>
      </div>

      {/* Glass control sheet */}
      <div style={{ position:'absolute', bottom:0, left:0, right:0, background:'rgba(26,24,18,0.55)', backdropFilter:'blur(24px) saturate(180%)', WebkitBackdropFilter:'blur(24px) saturate(180%)', borderRadius:'32px 32px 0 0', padding:'20px 22px 30px', color:'#fff', boxShadow:'0 -10px 40px rgba(0,0,0,0.25)' }}>
        <div style={{ display:'flex', alignItems:'baseline', justifyContent:'space-between', marginBottom:4 }}>
          <span style={{ fontSize:11, color:'var(--w-yellow)', fontWeight:700, letterSpacing:0.5, textTransform:'uppercase' }}>Stop {stopIdx+1} of {STOPS.length}</span>
          <span style={{ fontSize:11, opacity:0.7, fontWeight:600 }}>{Math.round(progress*7)}:{String(Math.round(progress*60)%60).padStart(2,'0')} / 7:00</span>
        </div>
        <div className="t-display" style={{ fontSize:26, fontWeight:600, lineHeight:1.1 }}>{stop.name}</div>
        <div style={{ fontSize:13, opacity:0.75, marginTop:4, fontStyle:'italic', fontFamily:'var(--w-display)' }}>"{stop.blurb}"</div>

        {/* Live location hint: arrival state or distance to the next stop */}
        {geo && geo.coords && (
          <div style={{ display:'flex', alignItems:'center', gap:8, marginTop:10, fontSize:12.5, fontWeight:700 }}>
            {atCurrent ? (
              <span style={{ display:'inline-flex', alignItems:'center', gap:6, padding:'5px 11px', borderRadius:999, background:'rgba(45,212,167,0.22)', color:'#7CF0CE' }}>
                <span style={{ width:7, height:7, borderRadius:4, background:'#2DD4A7', boxShadow:'0 0 0 3px rgba(45,212,167,0.3)' }}/> You're here
              </span>
            ) : nextStop && distToNext != null ? (
              <span style={{ display:'inline-flex', alignItems:'center', gap:6, padding:'5px 11px', borderRadius:999, background:'rgba(255,255,255,0.1)', color:'#fff' }}>
                <Icon.arrow size={13} color="var(--w-yellow)"/> Next: {nextStop.name} · {geo.formatDistance(distToNext)} · {geo.walkMins(distToNext)} min
              </span>
            ) : null}
            {geo.mode === 'sim' && (
              <span style={{ fontSize:10.5, fontWeight:700, color:'rgba(255,255,255,0.55)', display:'inline-flex', alignItems:'center', gap:4 }}>🧭 demo</span>
            )}
          </div>
        )}

        <Waveform progress={progress} playing={playing}/>

        <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginTop:18 }}>
          <button style={ctrlBtn(40)}><Icon.back15 size={22} color="#fff"/></button>
          <button onClick={()=>setStopIdx(Math.max(0,stopIdx-1))} style={ctrlBtn(48)}>
            <svg viewBox="0 0 24 24" width="20" height="20" fill="#fff"><path d="M19 5v14l-9-7zM5 5h3v14H5z"/></svg>
          </button>
          <button onClick={()=>setPlaying(!playing)} style={{ width:72, height:72, borderRadius:36, border:'none', cursor:'pointer', background:'var(--w-yellow)', color:'var(--w-yellow-ink)', boxShadow:'0 8px 24px rgba(255,201,60,0.5)', display:'flex', alignItems:'center', justifyContent:'center' }}>
            {playing ? <Icon.pause size={26} color="var(--w-yellow-ink)"/> : <Icon.play size={28} color="var(--w-yellow-ink)"/>}
          </button>
          <button onClick={()=>setStopIdx(Math.min(STOPS.length-1,stopIdx+1))} style={ctrlBtn(48)}><Icon.skip size={20} color="#fff"/></button>
          <button style={ctrlBtn(40)}><Icon.fwd15 size={22} color="#fff"/></button>
        </div>

        <div style={{ display:'flex', gap:8, marginTop:18 }}>
          {[{id:'story',label:'Story',i:<Icon.text size={14} color="currentColor"/>},{id:'ar',label:'AR',i:<Icon.ar size={14} color="currentColor"/>},{id:'quiz',label:'Quiz',i:<Icon.quiz size={14} color="currentColor"/>}].map(t => (
            <button key={t.id} onClick={()=>setTab(t.id)} style={{ flex:1, height:44, borderRadius:14, border:'none', cursor:'pointer', background:tab===t.id?'rgba(255,201,60,0.18)':'rgba(255,255,255,0.08)', color:tab===t.id?'var(--w-yellow)':'#fff', fontWeight:700, fontSize:13, fontFamily:'inherit', display:'flex', alignItems:'center', justifyContent:'center', gap:6, transition:'all .2s' }}>{t.i} {t.label}</button>
          ))}
        </div>

        <StopPanel tab={tab} stop={stop}/>
      </div>
    </div>
  );
}

const ctrlBtn = (size) => ({ width:size, height:size, borderRadius:size/2, background:'rgba(255,255,255,0.1)', border:'none', cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center' });

function Waveform({ progress, playing }) {
  const bars = 56;
  return (
    <div style={{ display:'flex', gap:2.5, alignItems:'center', height:36, marginTop:14 }}>
      {Array.from({length:bars}).map((_,i) => {
        const passed = i/bars < progress;
        const h = 8 + Math.sin(i*0.7)*6 + Math.sin(i*1.3)*8 + 14;
        return <div key={i} style={{ flex:1, height:Math.max(4,h), borderRadius:1.5, background:passed?'var(--w-yellow)':'rgba(255,255,255,0.3)', animation:playing&&passed?`wWave 1s ${i*0.04}s ease-in-out infinite`:'none', transformOrigin:'center' }}/>;
      })}
    </div>
  );
}

// Tabbed content beneath the player controls: narration, facts, or a quiz.
function StopPanel({ tab, stop }) {
  const wrap = { marginTop:16, maxHeight:184, overflowY:'auto', borderRadius:16, background:'rgba(0,0,0,0.18)', padding:'14px 16px', WebkitOverflowScrolling:'touch' };

  if (tab==='ar') {
    return (
      <div style={{ ...wrap, textAlign:'center', color:'rgba(255,255,255,0.8)' }}>
        <div style={{ fontSize:30, marginBottom:6 }}>📍</div>
        <div style={{ fontWeight:700, fontSize:14, color:'#fff' }}>Point your camera at {stop.name}</div>
        <div style={{ fontSize:12.5, marginTop:5, lineHeight:1.45 }}>Hold up your phone on-site to see AR overlays anchored to the landmark in front of you.</div>
      </div>
    );
  }

  if (tab==='quiz') {
    const fact = (stop.facts && stop.facts[0]) || stop.blurb;
    return (
      <div style={wrap}>
        <div style={{ fontSize:11, fontWeight:700, letterSpacing:0.5, textTransform:'uppercase', color:'var(--w-yellow)', marginBottom:8 }}>Quick quiz</div>
        <div style={{ fontWeight:600, fontSize:14.5, color:'#fff', lineHeight:1.4 }}>What's the one thing to remember about {stop.name}?</div>
        <div style={{ marginTop:10, fontSize:13, color:'rgba(255,255,255,0.85)', lineHeight:1.5, padding:'10px 12px', borderRadius:12, background:'rgba(255,201,60,0.14)' }}>💡 {fact}</div>
      </div>
    );
  }

  // story (default)
  return (
    <div style={wrap}>
      {stop.facts && stop.facts.length>0 && (
        <div style={{ display:'flex', flexDirection:'column', gap:6, marginBottom:12 }}>
          {stop.facts.map((f,i) => (
            <div key={i} style={{ display:'flex', gap:8, alignItems:'flex-start', fontSize:12.5, color:'rgba(255,255,255,0.85)', lineHeight:1.4 }}>
              <span style={{ color:'var(--w-yellow)', fontWeight:800, flexShrink:0 }}>›</span>
              <span>{f}</span>
            </div>
          ))}
        </div>
      )}
      {stop.narration && (
        <p style={{ margin:0, fontSize:13.5, lineHeight:1.6, color:'rgba(255,255,255,0.92)' }}>{stop.narration}</p>
      )}
    </div>
  );
}

Object.assign(window, { PlayerScreen });
