/* interactives-a.jsx — Flashcards, Hotspot diagram, Quiz, Journal */
const { useState: aState, useEffect: aEffect, useRef: aRef } = React;

/* ============ Tool shell ============ */
function Tool({ icon, kicker, title, children }) {
  return (
    <section className="card card-pad enter" style={{ marginTop: 22 }}>
      <div className="row gap-10" style={{ marginBottom: 14 }}>
        <span style={{ width: 40, height: 40, borderRadius: 12, display: 'grid', placeItems: 'center',
          background: 'var(--lime-soft)', color: 'var(--lime-strong)', flex: 'none' }}>
          <Icon name={icon} size={22} />
        </span>
        <div className="col" style={{ flex: 1, minWidth: 0 }}>
          <span className="eyebrow" style={{ fontSize: 11 }}>{kicker}</span>
          <h3 style={{ fontSize: 21 }}>{title}</h3>
        </div>
      </div>
      {children}
    </section>
  );
}

/* ============ Skeleton loader ============ */
function Skeleton({ height = 20, width = '100%', radius = 8 }) {
  return (
    <div style={{ height, width, borderRadius: radius, background: 'var(--bg-2)',
      animation: 'shimmer 1.5s infinite linear', backgroundSize: '200% 100%',
      backgroundImage: 'linear-gradient(90deg, var(--bg-2) 25%, var(--surface-2) 50%, var(--bg-2) 75%)' }} />
  );
}

/* ============ Flashcards ============ */
const FLASHCARDS = [
  { t: "Presence", d: "The feeling of “being there” — when a learner's brain accepts the virtual environment as real enough to respond to naturally." },
  { t: "Immersion", d: "The objective level of sensory information a system provides. More visual, audio and tracking fidelity = higher immersion." },
  { t: "Engagement", d: "Sustained attention and emotional investment in a task. Immersive presence tends to raise engagement and recall." },
  { t: "Degrees of freedom", d: "How a headset tracks movement. 3DoF tracks head rotation only; 6DoF also tracks position as you move through space." },
  { t: "Cybersickness", d: "Discomfort (nausea, dizziness) from a mismatch between what the eyes see and the body feels. Shorter sessions and comfort settings reduce it." },
];
function Flashcards() {
  const [i, setI] = aState(0);
  const [flip, setFlip] = aState(false);
  const [known, setKnown] = usePersist('fc_known', []);
  const card = FLASHCARDS[i];
  const go = (d) => { setFlip(false); setTimeout(() => setI((i + d + FLASHCARDS.length) % FLASHCARDS.length), 120); };
  const markKnown = () => { if (!known.includes(i)) setKnown([...known, i]); go(1); };
  return (
    <Tool icon="cards" kicker="Active recall" title="Key concept flashcards">
      <p className="muted" style={{ marginBottom: 16 }}>Tap a card to flip it. Quiz yourself before you read the back — it doubles what you remember.</p>
      <div style={{ maxWidth: 540, margin: '0 auto' }}>
        <button onClick={() => setFlip(f => !f)} aria-label="Flip card" style={{
          border: 'none', background: 'none', padding: 0, margin: 0, font: 'inherit',
          cursor: 'pointer', display: 'block', width: '100%', height: 230, position: 'relative'
        }}>
          {[false, true].map((back) => {
            const shown = back === flip;
            return (
            <div key={String(back)} style={{
              position: 'absolute', inset: 0,
              opacity: shown ? 1 : 0, transform: shown ? 'none' : 'scale(.96)',
              pointerEvents: shown ? 'auto' : 'none',
              transition: 'opacity .28s var(--ease), transform .28s var(--ease)',
              borderRadius: 'var(--radius-lg)', border: '1px solid var(--border)',
              background: back ? 'var(--lime-soft)' : 'var(--surface)', boxShadow: 'var(--shadow)',
              display: 'grid', placeItems: 'center', padding: 32, textAlign: 'center'
            }}>
              {!back ? (
                <div>
                  <span className="muted" style={{ fontSize: 13, fontWeight: 800, letterSpacing: '.08em', textTransform: 'uppercase' }}>Term</span>
                  <h3 style={{ fontSize: 34, marginTop: 10 }}>{card.t}</h3>
                  <span className="muted" style={{ fontSize: 14, marginTop: 16, display: 'block' }}>tap to reveal ↓</span>
                </div>
              ) : (
                <p style={{ fontSize: 19, color: 'var(--text)', fontWeight: 600, lineHeight: 1.5 }}>{card.d}</p>
              )}
            </div>
            );
          })}
        </button>
      </div>
      <div className="row" style={{ justifyContent: 'space-between', marginTop: 18 }}>
        <button className="btn btn-ghost btn-sm" onClick={() => go(-1)}><Icon name="chevron" size={16} style={{ transform: 'rotate(180deg)' }} /> Prev</button>
        <span className="muted" style={{ fontWeight: 700 }}>Card {i + 1} of {FLASHCARDS.length} · {known.length} known</span>
        <div className="row gap-10">
          <button className="btn btn-soft btn-sm" onClick={markKnown}><Icon name="check" size={16} /> I know this</button>
          <button className="btn btn-ghost btn-sm" onClick={() => go(1)}>Next <Icon name="chevron" size={16} /></button>
        </div>
      </div>
    </Tool>
  );
}

/* ============ Hotspot diagram ============ */
function Hotspot() {
  const data = window.EDSTUTIA.headset;
  const [active, setActive] = aState(data[0].id);
  const cur = data.find(d => d.id === active);
  return (
    <Tool icon="headset" kicker="Explore the hardware" title="Parts of the headset">
      <p className="muted" style={{ marginBottom: 16 }}>Click each numbered point to learn what it does and why it matters for comfort and accessibility.</p>
      <div className="grid" style={{ gridTemplateColumns: 'minmax(0,1.4fr) minmax(0,1fr)', gap: 22, alignItems: 'stretch' }}>
        <div style={{ position: 'relative', borderRadius: 'var(--radius)', minHeight: 320, overflow: 'hidden',
          border: '1px dashed var(--border-strong)',
          background: 'repeating-linear-gradient(135deg, var(--surface-2), var(--surface-2) 12px, var(--bg-2) 12px, var(--bg-2) 24px)' }}>
          <span style={{ position: 'absolute', top: 14, left: 16, fontFamily: 'monospace', fontSize: 12, color: 'var(--text-muted)', letterSpacing: '.04em' }}>
            [ photo: VR headset — 3/4 view ]
          </span>
          {data.map((d, n) => (
            <button key={d.id} onClick={() => setActive(d.id)} aria-label={d.label}
              style={{ position: 'absolute', left: d.x + '%', top: d.y + '%', transform: 'translate(-50%,-50%)',
                width: 40, height: 40, borderRadius: '50%', cursor: 'pointer', fontWeight: 800, fontSize: 16,
                fontFamily: 'var(--font-head)',
                border: '3px solid var(--surface)',
                background: active === d.id ? 'var(--lime)' : 'var(--brand-ink)',
                color: active === d.id ? '#14180D' : '#fff',
                boxShadow: active === d.id ? '0 0 0 6px var(--ring)' : 'var(--shadow)',
                transition: 'all .2s var(--ease)' }}>
              {n + 1}
            </button>
          ))}
        </div>
        <div className="card-pad" style={{ background: 'var(--lime-soft)', borderRadius: 'var(--radius)', display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
          <span className="eyebrow">Point {data.indexOf(cur) + 1}</span>
          <h3 style={{ fontSize: 24, margin: '6px 0 10px' }}>{cur.label}</h3>
          <p style={{ fontSize: 16.5, lineHeight: 1.55 }}>{cur.text}</p>
          <button className="btn btn-soft btn-sm" style={{ marginTop: 16, alignSelf: 'flex-start' }} onClick={() => speak(cur.label + '. ' + cur.text)}>
            <Icon name="volume" size={16} /> Read aloud
          </button>
        </div>
      </div>
    </Tool>
  );
}

/* ============ Knowledge-check quiz ============ */
const QUIZ = [
  { q: "A learner feels genuinely “present” in a virtual lab even though the graphics are simple. Which idea best explains this?",
    a: ["Higher immersion always equals higher presence", "Presence is a psychological response, not just hardware fidelity", "Presence requires a 6DoF headset", "Presence and engagement are the same thing"], correct: 1,
    why: "Presence is how real the experience feels to the learner — a psychological state that good design can create even on modest hardware." },
  { q: "Which design choice most directly helps reduce cybersickness for a first-time cohort?",
    a: ["Longer sessions to build tolerance", "Removing all comfort settings", "Shorter sessions with comfort options and breaks", "Maximum movement speed"], correct: 2,
    why: "Shorter sessions, comfort settings and regular breaks reduce the sensory mismatch that causes cybersickness — especially for newcomers." },
  { q: "You want students to move around an object and view it from any side. What does the headset need?",
    a: ["3 degrees of freedom (3DoF)", "6 degrees of freedom (6DoF)", "A desktop alternative only", "No tracking at all"], correct: 1,
    why: "6DoF tracks both rotation and position, so learners can physically walk around and inspect objects from every angle." },
];
function Quiz() {
  const [picked, setPicked] = aState({});
  const answered = Object.keys(picked).length;
  const score = QUIZ.reduce((s, q, i) => s + (picked[i] === q.correct ? 1 : 0), 0);
  return (
    <Tool icon="quiz" kicker="Check your understanding" title="Knowledge check">
      <p className="muted" style={{ marginBottom: 6 }}>No grades, no pressure — pick an answer to see instant feedback and a short explanation.</p>
      <div className="stack" style={{ marginTop: 16 }}>
        {QUIZ.map((q, i) => (
          <div key={i} className="card-pad" style={{ background: 'var(--surface-2)', borderRadius: 'var(--radius)', border: '1px solid var(--border)' }}>
            <p style={{ fontWeight: 800, fontFamily: 'var(--font-head)', fontSize: 18, marginBottom: 14 }}>{i + 1}. {q.q}</p>
            <div className="stack" style={{ '--space': '10px' }}>
              {q.a.map((opt, oi) => {
                const chosen = picked[i] === oi;
                const isCorrect = oi === q.correct;
                const show = picked[i] != null;
                let bg = 'var(--surface)', bd = 'var(--border)', col = 'var(--text)';
                if (show && isCorrect) { bg = 'color-mix(in srgb, var(--lime) 22%, var(--surface))'; bd = 'var(--lime)'; col = 'var(--lime-strong)'; }
                else if (show && chosen && !isCorrect) { bg = 'color-mix(in srgb, #E0584F 16%, var(--surface))'; bd = '#E0584F'; col = '#C0392B'; }
                return (
                  <button key={oi} disabled={show} onClick={() => setPicked({ ...picked, [i]: oi })}
                    style={{ display: 'flex', alignItems: 'center', gap: 12, width: '100%', textAlign: 'left',
                      padding: '13px 16px', marginTop: oi ? 10 : 0, borderRadius: 12, cursor: show ? 'default' : 'pointer',
                      border: '1.5px solid ' + bd, background: bg, color: col, fontFamily: 'var(--font-body)', fontSize: 16, fontWeight: 600,
                      transition: 'all .15s var(--ease)' }}>
                    <span style={{ width: 26, height: 26, borderRadius: '50%', border: '1.5px solid currentColor', display: 'grid', placeItems: 'center', flex: 'none', fontSize: 13, fontWeight: 800 }}>
                      {show && isCorrect ? <Icon name="check" size={15} /> : String.fromCharCode(65 + oi)}
                    </span>
                    {opt}
                  </button>
                );
              })}
            </div>
            {picked[i] != null && (
              <div className="row gap-10 enter" style={{ marginTop: 14, padding: 12, borderRadius: 12, background: 'var(--lime-soft)', alignItems: 'flex-start' }}>
                <Icon name="bulb" size={20} style={{ color: 'var(--lime-strong)', flex: 'none', marginTop: 2 }} />
                <p style={{ fontSize: 15.5, lineHeight: 1.5 }}>{q.why}</p>
              </div>
            )}
          </div>
        ))}
      </div>
      {answered === QUIZ.length && (
        <div className="row enter" style={{ marginTop: 18, justifyContent: 'center', gap: 14, padding: 18, borderRadius: 'var(--radius)', background: 'var(--lime-soft)' }}>
          <Icon name="trophy" size={28} style={{ color: 'var(--lime-strong)' }} />
          <p style={{ fontFamily: 'var(--font-head)', fontWeight: 800, fontSize: 19 }}>You got {score} of {QUIZ.length}. Nicely done, {window.EDSTUTIA.learner.first}!</p>
        </div>
      )}
    </Tool>
  );
}

/* ============ Reflection journal — Supabase-backed with autosave ============ */
function Journal({ prompt, id }) {
  const [text, setText] = aState('');
  const [saved, setSaved] = aState(false);
  const [loading, setLoading] = aState(true);
  const [syncing, setSyncing] = aState(false);
  const autoSaveTimer = aRef(null);
  const words = text.trim() ? text.trim().split(/\s+/).length : 0;

  // Load: try Supabase first, fallback to localStorage
  aEffect(() => {
    async function load() {
      // Show cached content immediately
      try {
        const cached = localStorage.getItem('eds_journal_' + id);
        if (cached) setText(JSON.parse(cached));
      } catch {}

      if (window.supabaseClient && window.ME_UUID) {
        const { data } = await window.supabaseClient
          .from('journal_entries')
          .select('content')
          .eq('user_id', window.ME_UUID)
          .eq('lesson_id', id)
          .maybeSingle();
        if (data?.content !== undefined) {
          setText(data.content);
          try { localStorage.setItem('eds_journal_' + id, JSON.stringify(data.content)); } catch {}
        }
      }
      setLoading(false);
    }
    load();
  }, [id]);

  // Autosave 2s after last keystroke
  aEffect(() => {
    if (loading) return;
    if (autoSaveTimer.current) clearTimeout(autoSaveTimer.current);
    autoSaveTimer.current = setTimeout(() => persistJournal(text, id), 2000);
    return () => { if (autoSaveTimer.current) clearTimeout(autoSaveTimer.current); };
  }, [text]);

  const persistJournal = async (content, lessonId) => {
    try { localStorage.setItem('eds_journal_' + lessonId, JSON.stringify(content)); } catch {}
    if (window.supabaseClient && window.ME_UUID) {
      setSyncing(true);
      await window.supabaseClient.from('journal_entries').upsert({
        user_id: window.ME_UUID,
        lesson_id: lessonId,
        content,
        updated_at: new Date().toISOString()
      }, { onConflict: 'user_id,lesson_id' });
      setSyncing(false);
    }
  };

  const saveNow = async () => {
    if (autoSaveTimer.current) clearTimeout(autoSaveTimer.current);
    await persistJournal(text, id);
    setSaved(true);
    setTimeout(() => setSaved(false), 1800);
  };

  return (
    <Tool icon="pen" kicker="Reflect &amp; connect" title="Reflection journal">
      <div className="row gap-10" style={{ alignItems: 'flex-start', marginBottom: 14, padding: 14, borderRadius: 12, background: 'var(--lime-soft)' }}>
        <Icon name="bulb" size={22} style={{ color: 'var(--lime-strong)', flex: 'none', marginTop: 2 }} />
        <p style={{ fontSize: 17, fontWeight: 700, lineHeight: 1.45 }}>{prompt}</p>
      </div>

      {loading ? (
        <div className="stack" style={{ gap: 10 }}>
          <Skeleton height={150} radius={12} />
        </div>
      ) : (
        <textarea value={text} onChange={e => setText(e.target.value)}
          placeholder="Write as much or as little as you like. Your journal saves automatically."
          style={{ width: '100%', minHeight: 150, resize: 'vertical', padding: 16, fontFamily: 'var(--font-body)',
            fontSize: 16.5, lineHeight: 1.6, borderRadius: 'var(--radius)', border: '1.5px solid var(--border)',
            background: 'var(--surface-2)', color: 'var(--text)', outline: 'none',
            transition: 'border-color .2s' }}
          onFocus={e => e.target.style.borderColor = 'var(--lime)'}
          onBlur={e => e.target.style.borderColor = 'var(--border)'}
        />
      )}

      <div className="row" style={{ justifyContent: 'space-between', marginTop: 12, flexWrap: 'wrap', gap: 10 }}>
        <span className="muted" style={{ fontWeight: 700, fontSize: 14 }}>
          {words} {words === 1 ? 'word' : 'words'}
          {syncing && <span style={{ marginLeft: 10, color: 'var(--text-muted)' }}>· saving…</span>}
          {!syncing && text && <span style={{ marginLeft: 10 }}>· saved</span>}
        </span>
        <div className="row gap-10">
          <button className="btn btn-soft btn-sm" onClick={() => speak(text)} disabled={!text.trim()}>
            <Icon name="volume" size={16} /> Read aloud
          </button>
          <button className="btn btn-primary btn-sm" onClick={saveNow} disabled={loading}>
            <Icon name={saved ? 'check' : 'flag'} size={16} /> {saved ? 'Saved!' : 'Save now'}
          </button>
        </div>
      </div>
    </Tool>
  );
}

Object.assign(window, { Tool, Skeleton, Flashcards, Hotspot, Quiz, Journal });
