// quest.jsx — reusable QuestPlayer + CompletionView + Quest tab
const { useState: useStateQ, useEffect: useEffectQ, useRef: useRefQ } = React;

// Circular countdown ring
function TimerRing({ progress, label, sub, tone = T.coral, size = 230 }) {
  const r = size / 2 - 12, c = 2 * Math.PI * r;
  return (
    <div style={{ position: 'relative', width: size, height: size, margin: '0 auto' }}>
      <svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}>
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke={T.surface2} strokeWidth="12"/>
        <circle cx={size/2} cy={size/2} r={r} fill="none" stroke={tone} strokeWidth="12" strokeLinecap="round"
          strokeDasharray={c} strokeDashoffset={c * (1 - progress)}
          style={{ transition: 'stroke-dashoffset 1s linear' }}/>
      </svg>
      <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
        <div style={{ fontSize: 56, fontWeight: 800, color: T.ink, letterSpacing: -1, fontVariantNumeric: 'tabular-nums' }}>{label}</div>
        {sub && <div style={{ fontSize: 14, color: T.ink3, fontWeight: 600, marginTop: -4 }}>{sub}</div>}
      </div>
    </div>
  );
}

// Quest Player — used by FTUE + main app
function QuestPlayer({ title, seconds, steps = [], avaLine, onDone, onClose, firstRun, tone = T.coral }) {
  const needCount = !firstRun && seconds >= 30;
  const [phase, setPhase] = useStateQ(needCount ? 'count' : 'run');
  const [count, setCount] = useStateQ(3);
  const [left, setLeft] = useStateQ(seconds);
  const [paused, setPaused] = useStateQ(false);

  useEffectQ(() => {
    if (phase !== 'count') return;
    if (count === 0) { setPhase('run'); return; }
    const t = setTimeout(() => setCount(c => c - 1), 700);
    return () => clearTimeout(t);
  }, [phase, count]);

  useEffectQ(() => {
    if (phase !== 'run' || paused) return;
    if (left <= 0) { const t = setTimeout(onDone, 500); return () => clearTimeout(t); }
    const t = setTimeout(() => setLeft(l => l - 1), 1000);
    return () => clearTimeout(t);
  }, [phase, left, paused]);

  if (phase === 'count') {
    return (
      <div style={{ position: 'absolute', inset: 0, background: T.ink, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <StatusBar light/>
        <div key={count} style={{ fontSize: 130, fontWeight: 800, color: '#fff', animation: 'popNum .6s ease' }}>{count === 0 ? '시작' : count}</div>
      </div>
    );
  }

  const mm = String(Math.floor(left / 60)).padStart(2, '0');
  const ss = String(left % 60).padStart(2, '0');
  return (
    <div style={{ position: 'absolute', inset: 0, background: T.surface, display: 'flex', flexDirection: 'column' }}>
      <StatusBar/>
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', padding: '54px 22px 0' }}>
        <TopBar title={title} right={
          <button onClick={onClose || onDone} style={{ width: 42, height: 42, borderRadius: 999, border: 'none', background: T.surface2, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <Icon name="close" size={20} color={T.ink2} sw={2.2}/>
          </button>}/>
        <div style={{ flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'center', gap: 22 }}>
          <TimerRing progress={1 - left / seconds} label={`${mm}:${ss}`} tone={tone}/>
          {/* steps */}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {steps.map((s, i) => (
              <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '12px 16px', background: T.bg, borderRadius: 16 }}>
                <div style={{ width: 26, height: 26, borderRadius: 999, background: tone === T.coral ? T.coralTint : T.calmSoft, color: tone, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 14, fontWeight: 800, flexShrink: 0 }}>{i + 1}</div>
                <div style={{ fontSize: 16, fontWeight: 600, color: T.ink, letterSpacing: -0.2 }}>{s}</div>
              </div>
            ))}
          </div>
          {avaLine && (
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '0 4px' }}>
              <AvaOrb size={34} speaking/>
              <div style={{ fontSize: 14.5, color: T.ink2, fontStyle: 'italic', fontWeight: 500 }}>“{avaLine}”</div>
            </div>
          )}
        </div>
      </div>
      <div style={{ padding: '14px 22px 32px', display: 'flex', gap: 12 }}>
        <Btn variant="soft" size="lg" style={{ flex: 1 }} onClick={() => setPaused(p => !p)} icon={<Icon name={paused ? 'play' : 'pause'} size={20} color={T.ink}/>}>{paused ? '재개' : '일시정지'}</Btn>
        <Btn variant={tone === T.coral ? 'primary' : 'calm'} size="lg" style={{ flex: 1.4 }} onClick={onDone}>완료</Btn>
      </div>
      <button onClick={onClose || onDone} style={{ position: 'absolute', bottom: 12, left: 0, right: 0, background: 'none', border: 'none', color: T.ink3, fontSize: 13, fontWeight: 600, cursor: 'pointer', fontFamily: 'inherit' }}>통증이 있으면 중단하세요</button>
    </div>
  );
}

// Completion + XP reward (game-feel celebration)
function CompletionView({ xp, streakDay, avaLine, primary, secondary, tertiary, firstRun, levelUp, pro, tone = T.coral }) {
  const [shownXp, setShownXp] = useStateQ(0);
  const [barFill, setBarFill] = useStateQ(false);
  const [shown, setShown] = useStateQ(false);
  const isCalm = tone === T.calm;
  useEffectQ(() => {
    const m = setTimeout(() => setShown(true), 40);
    const steps = 24, dur = 750; let i = 0;
    const iv = setInterval(() => { i++; setShownXp(Math.round((i / steps) * xp)); if (i >= steps) clearInterval(iv); }, dur / steps);
    const b = setTimeout(() => setBarFill(true), 450);
    return () => { clearInterval(iv); clearTimeout(b); clearTimeout(m); };
  }, []);
  const rise = (delay) => ({ opacity: shown ? 1 : 0, transform: shown ? 'translateY(0) scale(1)' : 'translateY(14px) scale(0.92)', transition: `opacity .5s ${delay}s, transform .55s ${delay}s cubic-bezier(.2,1.3,.4,1)` });

  const headline = firstRun ? '첫 Quest 완료!' : isCalm ? '회복 완료' : levelUp ? 'LEVEL UP!' : '완벽해요!';
  const accent = isCalm ? T.calm : T.good;

  return (
    <div style={{ position: 'absolute', inset: 0, background: `radial-gradient(120% 80% at 50% 0%, ${isCalm ? T.calmSoft : T.coralTint} 0%, ${T.bg} 55%)`, display: 'flex', flexDirection: 'column' }}>
      <StatusBar/>
      <Confetti/>
      <div style={{ position: 'absolute', top: 120, left: '50%', width: 280, height: 280, transform: 'translateX(-50%)', background: `conic-gradient(${accent}12 0deg 12deg, transparent 12deg 30deg)`, borderRadius: '50%', animation: 'spin 18s linear infinite', opacity: 0.7 }}/>
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', padding: '54px 30px 0', textAlign: 'center', position: 'relative', zIndex: 2 }}>
        {/* Ava celebrating */}
        <div style={{ position: 'relative', marginBottom: 18, ...rise(0) }}>
          <AvaOrb size={104} speaking/>
          <div style={{ position: 'absolute', top: -6, right: -10, width: 40, height: 40, borderRadius: '50%', background: T.good, display: 'flex', alignItems: 'center', justifyContent: 'center', boxShadow: `0 4px 0 #1E7A4F` }}>
            <Icon name="check" size={22} color="#fff" sw={3}/>
          </div>
        </div>

        <div style={{ fontSize: 34, fontWeight: 800, color: accent, letterSpacing: -0.8, marginBottom: 6, transform: 'rotate(-3deg)', ...rise(0.08) }}>{headline}</div>
        <div style={{ fontSize: 15.5, color: T.ink2, fontWeight: 600, marginBottom: 26, ...rise(0.12) }}>{firstRun ? '오늘의 첫 건강 행동이 기록됐어요' : '오늘 건강 행동이 기록됐어요'}</div>

        {/* reward tiles */}
        <div style={{ display: 'flex', gap: 12, marginBottom: 22 }}>
          <RewardTile icon="bolt" tone={T.coral} value={`+${shownXp}`} label="XP" style={rise(0.16)}/>
          <RewardTile icon="flame" tone={T.amber} value={firstRun ? '1' : streakDay} label="Day Streak" style={rise(0.26)}/>
          <RewardTile icon="bolt" tone={T.teal} value={pro ? '∞' : '+1'} label="Energy" style={rise(0.36)}/>
        </div>

        {/* XP bar */}
        <div style={{ width: '100%', maxWidth: 290, marginBottom: 22, ...rise(0.42) }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12.5, color: T.ink2, fontWeight: 800, marginBottom: 7 }}>
            <span>Lv.2 Daily Mover</span><span style={{ fontVariantNumeric: 'tabular-nums', whiteSpace: 'nowrap' }}>{barFill ? 120 : 80} / 200 XP</span>
          </div>
          <XPBar value={barFill ? 120 : 80} max={200} animate height={14}/>
        </div>

        {avaLine && (
          <div style={{ display: 'flex', alignItems: 'flex-start', gap: 11, textAlign: 'left', background: T.bg, padding: 16, borderRadius: 20, maxWidth: 330, boxShadow: '0 6px 20px rgba(28,27,25,0.06)', ...rise(0.48) }}>
            <AvaOrb size={36} speaking/>
            <div style={{ fontSize: 14.5, lineHeight: 1.5, color: T.ink, fontWeight: 500 }}>“{avaLine}”</div>
          </div>
        )}
      </div>
      <div style={{ padding: '14px 22px 30px', display: 'flex', flexDirection: 'column', gap: 8, position: 'relative', zIndex: 2 }}>
        {secondary && <Btn variant="soft" size="md" onClick={secondary.onClick}>{secondary.label}</Btn>}
        {tertiary && <Btn variant="ghost" size="sm" onClick={tertiary.onClick}>{tertiary.label}</Btn>}
        <Btn variant={isCalm ? 'calm' : 'primary'} onClick={primary.onClick}>{primary.label}</Btn>
      </div>
    </div>
  );
}

function RewardTile({ icon, tone, value, label, style }) {
  return (
    <div style={{ minWidth: 92, background: T.bg, borderRadius: 20, padding: '16px 12px 12px', boxShadow: `0 4px 0 ${T.surface2}, 0 10px 22px rgba(28,27,25,0.06)`, ...style }}>
      <div style={{ width: 40, height: 40, borderRadius: 12, background: tone, margin: '0 auto 8px', display: 'flex', alignItems: 'center', justifyContent: 'center', boxShadow: `0 3px 0 rgba(0,0,0,0.12)` }}>
        <Icon name={icon} size={22} color="#fff" fill="#fff" sw={icon === 'gem' || icon === 'flame' || icon === 'bolt' ? 0 : 2}/>
      </div>
      <div style={{ fontSize: 22, fontWeight: 800, color: T.ink, letterSpacing: -0.5, fontVariantNumeric: 'tabular-nums', lineHeight: 1 }}>{value}</div>
      <div style={{ fontSize: 11, fontWeight: 800, color: T.ink3, letterSpacing: 0.2, marginTop: 3 }}>{label}</div>
    </div>
  );
}

// celebratory confetti
function Confetti() {
  const bits = Array.from({ length: 44 });
  const cols = [T.coral, T.amber, T.calm, T.teal, T.good, T.pink];
  return (
    <div style={{ position: 'absolute', inset: 0, overflow: 'hidden', pointerEvents: 'none', zIndex: 5 }}>
      {bits.map((_, i) => {
        const round = i % 3 === 0;
        return (
          <div key={i} style={{
            position: 'absolute', top: -24, left: `${(i * 23) % 100}%`,
            width: round ? 9 : 7, height: round ? 9 : 13, borderRadius: round ? '50%' : 2,
            background: cols[i % cols.length],
            animation: `confetti ${1.5 + (i % 6) * 0.22}s ${(i % 9) * 0.07}s ease-in forwards`,
            transform: `rotate(${i * 33}deg)`,
          }}/>
        );
      })}
    </div>
  );
}

// ── "오늘의 라인" — transit-map journey (original, multi-color) ──
function TransitStation({ st, first, last, onStart }) {
  const c = catColor(st.cat);
  const isActive = st.state === 'active', isDone = st.state === 'done', isReward = st.state === 'reward', locked = st.state === 'locked';
  const dotColor = isDone ? T.good : isReward ? T.amber : isActive ? c.c : T.surface2;
  const dotLip = isDone ? '#1E7A4F' : isReward ? T.amberDark : isActive ? c.d : '#D9D5CD';
  return (
    <div style={{ display: 'flex', gap: 14, position: 'relative' }}>
      {/* rail */}
      <div style={{ position: 'relative', width: 30, flexShrink: 0, display: 'flex', justifyContent: 'center' }}>
        {!first && <div style={{ position: 'absolute', top: -10, height: 48, width: 4, borderRadius: 2, background: isDone || isActive ? c.c : T.surface2 }}/>}
        {!last && <div style={{ position: 'absolute', top: 38, bottom: -10, width: 4, borderRadius: 2, background: isDone ? c.c : T.surface2 }}/>}
        <div style={{ position: 'absolute', top: 26, width: isActive ? 30 : 24, height: isActive ? 30 : 24, borderRadius: '50%', background: dotColor, boxShadow: `0 4px 0 ${dotLip}`, display: 'flex', alignItems: 'center', justifyContent: 'center', animation: isActive ? 'nodePulse 1.8s ease-in-out infinite' : 'none' }}>
          {isDone ? <Icon name="check" size={14} color="#fff" sw={3}/> : isReward ? <Icon name="star" size={13} color="#fff" sw={0}/> : isActive ? <span style={{ width: 8, height: 8, borderRadius: '50%', background: '#fff' }}/> : <span style={{ width: 7, height: 7, borderRadius: '50%', background: T.ink3, opacity: 0.5 }}/>}
        </div>
      </div>
      {/* station card */}
      <button onClick={locked ? undefined : () => onStart(st)} style={{
        flex: 1, textAlign: 'left', border: 'none', cursor: locked ? 'default' : 'pointer', fontFamily: 'inherit',
        background: isActive ? T.bg : isDone ? c.s : T.bg, borderRadius: 22, padding: 15, marginBottom: 12,
        boxShadow: isActive ? `0 0 0 2.5px ${c.c}, 0 12px 26px ${c.c}26` : isDone ? 'none' : `0 2px 8px rgba(28,27,25,0.05)`,
        opacity: locked ? 0.6 : 1, display: 'flex', alignItems: 'center', gap: 13,
      }}>
        <div style={{ width: 46, height: 46, borderRadius: 14, flexShrink: 0, background: locked ? T.surface2 : isDone ? T.bg : c.s, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <Icon name={st.icon} size={23} color={locked ? T.ink3 : c.c} fill={st.icon === 'star' ? (locked ? T.ink3 : c.c) : 'none'} sw={st.icon === 'star' ? 0 : 2}/>
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 10.5, fontWeight: 800, color: locked ? T.ink3 : c.c, letterSpacing: 0.6 }}>{isReward ? 'BONUS' : c.label.toUpperCase()}</div>
          <div style={{ fontSize: 16.5, fontWeight: 800, color: locked ? T.ink3 : T.ink, letterSpacing: -0.3, marginTop: 1 }}>{st.title}</div>
          <div style={{ fontSize: 12.5, color: T.ink3, fontWeight: 600, marginTop: 2 }}>{st.meta}</div>
        </div>
        {isActive ? (
          <div style={{ flexShrink: 0, display: 'flex', alignItems: 'center', gap: 6, background: c.c, color: '#fff', borderRadius: 12, padding: '9px 14px', fontSize: 13.5, fontWeight: 800, boxShadow: `0 3px 0 ${c.d}` }}>START<Icon name="play" size={13} color="#fff"/></div>
        ) : isDone ? <Icon name="check" size={20} color={T.good} sw={2.6}/>
          : locked ? <Icon name="lock" size={17} color={T.ink3} sw={2}/>
          : <Icon name="chevron" size={18} color={T.ink3} sw={2.2}/>}
      </button>
    </div>
  );
}

function QuestTab({ go, data, startQuest }) {
  const done = data.completedToday;
  const stations = data.questStations || [
    { id: 'a', cat: 'mobility', icon: 'wind', title: '목·어깨 리셋', meta: '30초 · 앉아서', state: done ? 'done' : 'active', quest: { title: '어깨 리셋', seconds: 30, steps: ['어깨를 귀 쪽으로 올려요', '뒤로 천천히 크게 돌려요', '숨을 길게 내쉬어요'], avaLine: '속도보다 부드러움이 중요해요', xp: 10 } },
    { id: 'b', cat: 'strength', icon: 'dumbbell', title: '코어 세우기', meta: '20초 · 앉아서', state: done ? 'active' : 'locked', quest: { title: '코어 세우기', seconds: 20, tone: T.violet, steps: ['등을 곧게 세워요', '배에 힘을 줘요', '천천히 호흡해요'], avaLine: '허리가 아니라 배에 힘을', xp: 12 } },
    { id: 'c', cat: 'breath', icon: 'star', title: '보너스 상자', meta: '연속 2개 완료 시 열림', state: 'locked', reward: true },
    { id: 'd', cat: 'recovery', icon: 'leaf', title: '회복 호흡', meta: '30초 · 침대에서', state: 'locked', quest: { title: '회복 호흡', seconds: 30, tone: T.calm, steps: ['편하게 누워요', '4초 들이마셔요', '6초 내쉬어요'], avaLine: '회복도 훈련이에요', xp: 12 } },
    { id: 'e', cat: 'cardio', icon: 'bolt', title: '가볍게 흐르기', meta: '60초 · 서서', state: 'locked', quest: { title: '플로우', seconds: 60, tone: T.teal, steps: ['팔을 크게 돌려요', '제자리 걷기', '깊게 호흡해요'], avaLine: '천천히 리듬을 타요', xp: 18 } },
  ];
  const startStation = (s) => { if (s.reward) return; startQuest(s.quest); };

  return (
    <Screen bg={T.surface} nav="quest">
      {/* season banner — multi-hue */}
      <div style={{ margin: '6px 0 22px', borderRadius: 24, padding: '18px 20px', background: `linear-gradient(135deg, ${T.coral} 0%, ${T.violet} 100%)`, boxShadow: `0 8px 26px ${T.violet}33`, position: 'relative', overflow: 'hidden' }}>
        <div style={{ position: 'absolute', top: 0, left: 0, width: 70, height: '100%', background: 'rgba(255,255,255,0.22)', animation: 'shine 5s ease-in-out infinite' }}/>
        <div style={{ position: 'relative', display: 'flex', alignItems: 'center', gap: 14 }}>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 11.5, fontWeight: 800, color: 'rgba(255,255,255,0.85)', letterSpacing: 1 }}>SEASON 2 · 오늘의 라인</div>
            <div style={{ fontSize: 22, fontWeight: 800, color: '#fff', letterSpacing: -0.4, marginTop: 2 }}>몸을 깨우는 하루</div>
          </div>
          <div style={{ textAlign: 'center', background: 'rgba(255,255,255,0.2)', borderRadius: 16, padding: '8px 13px' }}>
            <div style={{ fontSize: 11, fontWeight: 700, color: 'rgba(255,255,255,0.9)' }}>완료</div>
            <div style={{ fontSize: 20, fontWeight: 800, color: '#fff' }}>{done ? 1 : 0}/1</div>
          </div>
        </div>
      </div>

      {/* transit line */}
      <div style={{ paddingLeft: 2 }}>
        {stations.map((s, i) => (
          <TransitStation key={s.id} st={s} first={i === 0} last={i === stations.length - 1} onStart={startStation}/>
        ))}
      </div>

      {/* swap */}
      <Card pad={16} style={{ margin: '8px 0 0', display: 'flex', alignItems: 'center', gap: 12 }}>
        <AvaOrb size={38} speaking/>
        <div style={{ flex: 1, fontSize: 14, color: T.ink, fontWeight: 500, lineHeight: 1.45 }}>컨디션이 별로면 더 쉬운 라인으로 바꿔도 점수는 그대로예요.</div>
        <button onClick={() => go('flow', { flow: 'swap' })} style={{ flexShrink: 0, background: T.coralSoft, color: T.coralDark, border: 'none', borderRadius: 12, padding: '10px 14px', fontSize: 13.5, fontWeight: 800, cursor: 'pointer', fontFamily: 'inherit', boxShadow: '0 3px 0 rgba(0,122,255,0.18)' }}>바꾸기</button>
      </Card>
      <div style={{ height: 16 }}/>
    </Screen>
  );
}

Object.assign(window, { QuestPlayer, CompletionView, QuestTab, TimerRing, Confetti, RewardTile });
