/* Poise onboarding - S1 Welcome: full-bleed film.
   Real people, warm light, confident stride. Stock placeholders - swap srcs
   for licensed brand footage. Exits with a film-style dip to black so the
   cut into S2's dark canvas reads as one continuous move. */

const { useState, useEffect, useRef } = React;
const { Button } = window.PoiseDesignSystem_eee0d2;

const FILM_CLIPS = [
  { src: 'https://www.pexels.com/download/video/17016628/', pos: '50% 30%', end: 16 },  // her, wide + close - first 16s only
  { src: 'https://www.pexels.com/download/video/9154730/', pos: '35% 0%', start: 3 },  // man on stairs - crop A panned left, first 3s trimmed
  { src: 'https://www.pexels.com/download/video/8164409/', pos: '50% 30%' },  // coffee woman - take 1 (longer)
];
const FILM_XFADE = 2400, FILM_INTRO = 700, FILM_EXIT = 900;

function WelcomeScreen({ prewarm = false }) {
  const flow = useFlow();
  /* Mount-time flag: when prewarmed under the splash, the root skips its own
     entrance animation (the splash crossfade IS the entrance) - and must keep
     skipping it after the handoff render, hence the ref. */
  const wasPrewarmed = useRef(prewarm);
  const [active, setActive] = useState(0);
  const [ready, setReady] = useState(() => FILM_CLIPS.map(() => null)); // null=loading, true=ok, false=failed
  const [leaving, setLeaving] = useState(false);
  const vids = useRef([]);

  const mark = (i, ok) => setReady((r) => (r[i] === ok ? r : r.map((x, j) => (j === i ? ok : x))));

  /* Park a clip at its trim-in point, paused, ready for a seek-free entrance */
  const park = (i) => {
    const v = vids.current[i];
    if (!v) return;
    v.pause();
    try { v.currentTime = FILM_CLIPS[i].start || 0; } catch (e) {}
  };

  /* If the active clip failed, fall to the first working one */
  useEffect(() => {
    if (ready[active] === false) {
      const ok = ready.findIndex((x) => x === true);
      if (ok >= 0) setActive(ok);
    }
  }, [ready, active]);

  /* Advance when the active clip finishes - each take plays in full (or to its end time if set). */
  const introDone = useRef(false);
  const advance = () => {
    introDone.current = true;
    setActive((a) => {
      for (let s = 1; s <= FILM_CLIPS.length; s++) {
        const i = (a + s) % FILM_CLIPS.length;
        if (ready[i] === true) return i;
      }
      return a;
    });
  };
  /* Begin the crossfade BEFORE the clip ends so both takes are still moving
     during the overlap - no freeze-frame at the cut. Guard so the tail only
     triggers one advance. */
  const advancedFrom = useRef(-1);
  const onTail = (i) => {
    const v = vids.current[i];
    if (i !== active || advancedFrom.current === i || !v || !v.duration) return;
    const clip = FILM_CLIPS[i];
    const endTime = clip.end || v.duration;
    if (endTime - v.currentTime <= FILM_XFADE / 1000) {
      advancedFrom.current = i;
      advance();
    }
  };
  useEffect(() => { advancedFrom.current = -1; }, [active]);
  useEffect(() => {
    if (!flow.t.motion || FILM_CLIPS.length < 2) return;
    /* Safety net: if 'ended' never fires (stalled stream), rotate after 45s */
    const id = setInterval(advance, 45000);
    return () => clearInterval(id);
  }, [ready, flow.t.motion]);

  /* Seek-free handoff: the incoming clip is already parked at its trim-in
     point, so we only play(). The outgoing clip keeps rolling through the
     fade, then gets parked for its next turn once fully hidden. */
  const prevActive = useRef(active);
  useEffect(() => {
    const v = vids.current[active];
    if (v && flow.t.motion) {
      v.playbackRate = FILM_CLIPS[active].rate || 1;
      const p = v.play(); if (p && p.catch) p.catch(() => {});
    }
    const out = prevActive.current;
    prevActive.current = active;
    if (out === active) return;
    const id = setTimeout(() => park(out), FILM_XFADE + 200);
    return () => clearTimeout(id);
  }, [active]);

  /* Stop video at its end time if specified */
  useEffect(() => {
    const v = vids.current[active];
    if (!v) return;
    const clip = FILM_CLIPS[active];
    if (!clip.end) return;
    
    const checkEnd = () => {
      if (v.currentTime >= clip.end) {
        v.pause();
        advance();
      }
    };
    
    v.addEventListener('timeupdate', checkEnd);
    return () => v.removeEventListener('timeupdate', checkEnd);
  }, [active]);

  /* On load: set rate; park everything except the active clip */
  const onClipReady = (i) => {
    const v = vids.current[i];
    if (v) v.playbackRate = FILM_CLIPS[i].rate || 1;
    mark(i, true);
    if (i !== active) park(i);
    else if (v && flow.t.motion && (FILM_CLIPS[i].start || 0) > 0 && v.currentTime < FILM_CLIPS[i].start) {
      try { v.currentTime = FILM_CLIPS[i].start; } catch (e) {}
    }
  };

  /* Motion toggle: pause everything; resume only the active clip */
  useEffect(() => {
    vids.current.forEach((v, i) => {
      if (!v) return;
      if (flow.t.motion && i === active) { const p = v.play(); if (p && p.catch) p.catch(() => {}); } else { v.pause(); }
    });
  }, [flow.t.motion]);

  /* Exit: dip to black, then advance. Footage keeps rolling as it dims. */
  const begin = () => {
    if (leaving) return;
    setLeaving(true);
    setTimeout(() => flow.next(), flow.t.motion ? FILM_EXIT : 30);
  };

  const anyVideo = ready.some((x) => x === true);

  return (
    <div data-screen-label="S1 · Welcome (film)" className={wasPrewarmed.current ? undefined : 'onb-screen-enter'} style={{ position: 'absolute', inset: 0, background: 'var(--black)', overflow: 'hidden' }}>
      {FILM_CLIPS.map((c, i) => (
        <video
          key={c.src}
          ref={(el) => { vids.current[i] = el; }}
          src={c.src}
          muted playsInline autoPlay preload="auto"
          loop={FILM_CLIPS.length < 2}
          onTimeUpdate={() => onTail(i)}
          onEnded={() => { if (i === active) advance(); }}
          onCanPlay={() => onClipReady(i)}
          onError={() => mark(i, false)}
          className={flow.t.motion ? 'film-zoom' : ''}
          style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: c.pos, opacity: ready[i] === true && i === active ? 1 : 0, transition: `opacity ${introDone.current ? FILM_XFADE : FILM_INTRO}ms cubic-bezier(0.45, 0, 0.3, 1)`, filter: 'saturate(0.88) brightness(0.9) contrast(1.05)' }}>
        </video>
      ))}

      {/* Scrim: legible status bar up top, type bed at the bottom */}
      <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(180deg, rgba(2,0,3,0.55) 0%, rgba(2,0,3,0.1) 20%, rgba(2,0,3,0) 42%, rgba(2,0,3,0.3) 62%, rgba(2,0,3,0.88) 82%, #020003 100%)' }}></div>

      {/* Wordmark, under the status bar (16px clearance below whatever's
          rendered above it - the bar itself, or just the screen edge when
          PhoneShell renders without one) */}
      <div className="rise" style={{ position: 'absolute', top: 'calc(var(--status-bar-inset) + 16px)', left: 'var(--screen-margin)', opacity: leaving ? 0 : undefined, transition: 'opacity 450ms var(--ease-out)' }}>
        <Wordmark size={30} />
      </div>

      {/* Type + CTA */}
      <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, display: 'flex', flexDirection: 'column', padding: '0 var(--screen-margin) 34px', opacity: leaving ? 0 : 1, transform: leaving ? 'translateY(6px)' : 'none', transition: 'opacity 450ms var(--ease-out), transform 450ms var(--ease-out)' }}>
        <div className="film-headline rise" style={{ animationDelay: '250ms' }}>Carry yourself well.</div>
        <P style={{ fontSize: 17, margin: '12px 0 28px', color: 'rgba(233, 231, 234, 0.82)' }}>
          <span className="rise" style={{ display: 'inline-block', animationDelay: '500ms' }}>Quiet posture coaching through the AirPods you already own.</span>
        </P>
        <div className="rise" style={{ animationDelay: '800ms' }}>
          <Button variant="primary" size="lg" fullWidth onClick={begin}>Get started</Button>
        </div>
      </div>

      {/* Dip to black on exit - sits over footage and scrim */}
      <div style={{ position: 'absolute', inset: 0, background: 'var(--black)', opacity: leaving ? 1 : 0, transition: `opacity ${FILM_EXIT}ms cubic-bezier(0.33, 0, 0.55, 1)`, pointerEvents: 'none', zIndex: 5 }}></div>
    </div>
  );
}

Object.assign(window, { WelcomeScreen });
