// reader-activities.jsx — interactive lesson activities + local answer storage.
// Design intent: JY groups mostly answer aloud and in their printed books, so the
// app keeps answering OPTIONAL and private. Open-ended prompts get a text box that
// saves only to this device (nothing is sent anywhere). Multiple-choice and
// fill-in are interactive with gentle self-check, which works well for solo review.
function useLocal(key, init) {
  const [v, setV] = React.useState(() => { try { const s = localStorage.getItem(key); return s != null ? JSON.parse(s) : init; } catch { return init; } });
  React.useEffect(() => { try { localStorage.setItem(key, JSON.stringify(v)); } catch {} }, [key, v]);
  return [v, setV];
}

function ActLabel({ children }) {
  const c = useTheme();
  return <div style={{ fontSize: 11.5, fontWeight: 700, letterSpacing: '0.06em', textTransform: 'uppercase', color: c.accent, marginBottom: 10 }}>{children}</div>;
}

function AnswerField({ base }) {
  const c = useTheme();
  const [val, setVal] = useLocal(base, '');
  return (
    <textarea value={val} onChange={e => setVal(e.target.value)} placeholder={c.t('act_optional')} rows={2} style={{
      width: '100%', boxSizing: 'border-box', marginTop: 10, resize: 'none', borderRadius: 11, padding: '10px 12px',
      border: `1px dashed ${c.border}`, background: c.surfaceAlt, color: c.text, fontFamily: 'inherit', fontSize: 14.5, lineHeight: 1.45, outline: 'none',
    }} />
  );
}

function QuestionsBlock({ s, base }) {
  const c = useTheme();
  const items = c.L(s.items);
  return (
    <div>
      <ActLabel>{c.L(s.label)}</ActLabel>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {items.map((q, j) => (
          <div key={j} style={{ ...asfCard(c), padding: '14px 15px' }}>
            <div style={{ display: 'flex', gap: 11, alignItems: 'flex-start' }}>
              <div style={{ fontFamily: c.headingStack, fontWeight: 700, fontSize: 15, color: c.accent, flexShrink: 0 }}>{j + 1}</div>
              <p style={{ margin: 0, fontSize: 15, lineHeight: 1.45, color: c.text }}>{q}</p>
            </div>
            <AnswerField base={`${base}_${j}`} />
          </div>
        ))}
      </div>
    </div>
  );
}

function ChoiceBlock({ s, base }) {
  const c = useTheme();
  return (
    <div>
      <ActLabel>{c.L(s.label)}</ActLabel>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        {s.items.map((it, j) => <ChoiceItem key={j} it={it} base={`${base}_${j}`} n={j + 1} />)}
      </div>
    </div>
  );
}
function ChoiceItem({ it, base, n }) {
  const c = useTheme();
  const [sel, setSel] = useLocal(base, null);
  const opts = c.L(it.options);
  const letters = ['a', 'b', 'c', 'd'];
  return (
    <div style={{ ...asfCard(c), padding: '14px 15px' }}>
      <div style={{ display: 'flex', gap: 11, alignItems: 'flex-start', marginBottom: 10 }}>
        <div style={{ fontFamily: c.headingStack, fontWeight: 700, fontSize: 15, color: c.accent, flexShrink: 0 }}>{n}</div>
        <p style={{ margin: 0, fontSize: 15, lineHeight: 1.45, color: c.text, fontWeight: 600 }}>{c.L(it.q)}</p>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
        {opts.map((o, k) => {
          const chosen = sel === k;
          const isAnswer = k === it.answer;
          const revealed = sel != null;
          let bg = c.surfaceAlt, fg = c.text, bd = c.border;
          if (revealed && isAnswer) { bg = c.accentSoft; bd = c.accent; }
          if (revealed && chosen && !isAnswer) { bg = 'transparent'; fg = c.textMuted; }
          return (
            <button key={k} onClick={() => setSel(k)} style={{
              display: 'flex', alignItems: 'center', gap: 10, textAlign: 'left', cursor: 'pointer',
              border: `1.5px solid ${bd}`, background: bg, color: fg, borderRadius: 11, padding: '10px 12px', fontFamily: 'inherit', fontSize: 14.5, lineHeight: 1.35,
            }}>
              <span style={{ fontWeight: 800, color: revealed && isAnswer ? c.accent : c.textMuted, flexShrink: 0 }}>{letters[k]}</span>
              <span style={{ flex: 1 }}>{o}</span>
              {revealed && isAnswer && <span style={{ color: c.accent, flexShrink: 0 }}><Icon name="check" size={16} /></span>}
            </button>
          );
        })}
      </div>
      {sel != null && (
        <div style={{ marginTop: 9, fontSize: 13, fontWeight: 700, color: sel === it.answer ? c.accent : c.textMuted }}>
          {sel === it.answer ? c.t('act_nice') : c.t('act_not_quite')}
        </div>
      )}
    </div>
  );
}

function WordbankBlock({ s, base }) {
  const c = useTheme();
  const words = c.L(s.words);
  const [val, setVal] = useLocal(base, '');
  return (
    <div>
      <ActLabel>{c.L(s.label)}</ActLabel>
      <p style={{ margin: '0 0 12px', fontSize: 15, lineHeight: 1.5, color: c.textMuted }}>{c.L(s.prompt)}</p>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: 12 }}>
        {words.map((w, j) => (
          <span key={j} style={{ padding: '7px 13px', borderRadius: 999, background: c.surface, color: c.text, fontSize: 14, fontWeight: 600, boxShadow: `inset 0 0 0 1px ${c.border}` }}>{w}</span>
        ))}
      </div>
      <textarea value={val} onChange={e => setVal(e.target.value)} placeholder={c.t('act_optional')} rows={6} style={{
        width: '100%', boxSizing: 'border-box', resize: 'none', borderRadius: 13, padding: '14px', lineHeight: 1.6,
        border: `1px dashed ${c.border}`, background: c.surfaceAlt, color: c.text, fontFamily: 'inherit', fontSize: 15, outline: 'none',
      }} />
    </div>
  );
}

function FillbankBlock({ s, base }) {
  const c = useTheme();
  const words = c.L(s.words);
  const [filled, setFilled] = useLocal(base, {});   // { itemIdx: word }
  const [active, setActive] = React.useState(null);
  const norm = (x) => (x || '').toLowerCase().trim();
  const usedCount = {}; Object.values(filled).forEach(w => { usedCount[norm(w)] = (usedCount[norm(w)] || 0) + 1; });

  const placeWord = (w) => {
    if (active == null) return;
    setFilled(f => ({ ...f, [active]: w }));
    // advance to next empty blank
    const next = s.items.findIndex((_, i) => i > active && !filled[i]);
    setActive(next === -1 ? null : next);
  };
  const clearBlank = (i) => { setFilled(f => { const n = { ...f }; delete n[i]; return n; }); setActive(i); };

  return (
    <div>
      <ActLabel>{c.L(s.label)}</ActLabel>
      <p style={{ margin: '0 0 6px', fontSize: 15, lineHeight: 1.5, color: c.textMuted }}>{c.L(s.prompt)}</p>
      <div style={{ fontSize: 12.5, color: c.textMuted, marginBottom: 10, fontStyle: 'italic' }}>{c.t('act_tap_blank')}</div>

      {/* word bank */}
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: 16 }}>
        {words.map((w, j) => {
          const used = (usedCount[norm(w)] || 0) > 0;
          return (
            <button key={j} disabled={active == null || used} onClick={() => placeWord(w)} style={{
              padding: '8px 14px', borderRadius: 999, border: 'none', cursor: active != null && !used ? 'pointer' : 'default',
              background: used ? 'transparent' : (active != null ? c.accent : c.surface), color: used ? c.faint : (active != null ? c.accentInk : c.text),
              fontSize: 14, fontWeight: 700, boxShadow: used ? `inset 0 0 0 1px ${c.border}` : (active != null ? 'none' : `inset 0 0 0 1px ${c.border}`),
              textDecoration: used ? 'line-through' : 'none', opacity: used ? 0.5 : 1,
            }}>{w}</button>
          );
        })}
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 11 }}>
        {s.items.map((it, i) => {
          const parts = c.L(it.text).split('___');
          const word = filled[i];
          const correct = word && norm(word) === norm(c.L(it.answer));
          const isActive = active === i;
          let blankBg = c.surfaceAlt, blankFg = c.textMuted, blankBd = c.border;
          if (isActive) { blankBd = c.accent; blankBg = c.accentSoft; }
          if (word) { blankFg = correct ? c.accent : '#c0563f'; blankBd = correct ? c.accent : '#c0563f'; blankBg = c.surface; }
          return (
            <div key={i} style={{ ...asfCard(c), padding: '13px 15px', display: 'flex', gap: 10, alignItems: 'baseline' }}>
              <span style={{ fontFamily: c.headingStack, fontWeight: 700, fontSize: 14, color: c.accent, flexShrink: 0 }}>{i + 1}</span>
              <p style={{ margin: 0, fontSize: 15.5, lineHeight: 1.7, color: c.text }}>
                {parts[0]}
                <button onClick={() => (word ? clearBlank(i) : setActive(i))} style={{
                  border: `1.5px solid ${blankBd}`, background: blankBg, color: blankFg, cursor: 'pointer',
                  borderRadius: 8, padding: '1px 12px', margin: '0 3px', fontFamily: 'inherit', fontSize: 14.5, fontWeight: 700, verticalAlign: 'baseline',
                  display: 'inline-flex', alignItems: 'center', gap: 5, minWidth: 56, justifyContent: 'center',
                }}>{word || '·····'}{word && correct && <Icon name="check" size={13} />}</button>
                {parts[1]}
              </p>
            </div>
          );
        })}
      </div>

      <button onClick={() => { setFilled({}); setActive(null); }} style={{
        marginTop: 14, border: `1px solid ${c.border}`, background: 'transparent', color: c.textMuted, cursor: 'pointer',
        fontFamily: 'inherit', fontWeight: 700, fontSize: 14, padding: '11px', borderRadius: 12, width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 7,
      }}><Icon name="refresh" size={16} />{c.t('act_reset')}</button>
    </div>
  );
}

function AttentionBlock({ s, base }) {
  const c = useTheme();
  const [marked, setMarked] = useLocal(`${base}_pairs`, {});
  const [wordMarks, setWordMarks] = useLocal(`${base}_words`, {});
  const cycleWord = (idx) => setWordMarks(m => {
    const cur = m[idx] || '';
    const next = cur === '' ? 'circle' : (cur === 'circle' ? 'square' : '');
    const copy = { ...m };
    if (next) copy[idx] = next; else delete copy[idx];
    return copy;
  });

  return (
    <div>
      <ActLabel>{c.L(s.label)}</ActLabel>
      {s.intro && <p style={{ margin: '0 0 13px', fontSize: 15.5, lineHeight: 1.55, color: c.text }}>{c.L(s.intro)}</p>}
      <p style={{ margin: '0 0 13px', fontSize: 15, lineHeight: 1.5, color: c.textMuted }}>{c.L(s.prompt)}</p>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
        {s.shapeSets.map((set, setIdx) => (
          <div key={setIdx} style={{ ...asfCard(c), padding: '14px 14px 15px' }}>
            <div style={{ display: 'flex', gap: 9, alignItems: 'baseline', marginBottom: 12 }}>
              <div style={{ fontFamily: c.headingStack, fontWeight: 900, color: c.accent, minWidth: 22 }}>{c.L(set.title)}</div>
              <div style={{ fontSize: 15, color: c.text, lineHeight: 1.4 }}>{c.L(set.hint)}</div>
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, minmax(0, 1fr))', gap: 9 }}>
              {set.pairs.map((pair, pairIdx) => {
                const key = `${setIdx}_${pairIdx}`;
                const on = !!marked[key];
                return (
                  <button key={key} onClick={() => setMarked(m => ({ ...m, [key]: !m[key] }))} style={{
                    minHeight: 64, borderRadius: 13, border: `1.5px solid ${on ? c.accent : c.border}`,
                    background: on ? c.accentSoft : c.surfaceAlt,
                    cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 11,
                    position: 'relative',
                  }}>
                    <ShapeIcon type={pair[0]} />
                    <ShapeIcon type={pair[1]} />
                  </button>
                );
              })}
            </div>
          </div>
        ))}

        {s.afterShapes && c.L(s.afterShapes).map((q, i) => (
          <div key={`shape-q-${i}`} style={{ ...asfCard(c), padding: '13px 15px' }}>
            <p style={{ margin: 0, fontSize: 15, lineHeight: 1.45, color: c.text }}>{q}</p>
            <AnswerField base={`${base}_shape_q_${i}`} />
          </div>
        ))}

        <div style={{ ...asfCard(c), padding: '14px 14px 15px' }}>
          <div style={{ display: 'flex', gap: 9, alignItems: 'baseline', marginBottom: 12 }}>
            <div style={{ fontFamily: c.headingStack, fontWeight: 900, color: c.accent, minWidth: 22 }}>c.</div>
            <div style={{ fontSize: 15, color: c.text, lineHeight: 1.4 }}>
              {c.L(s.arrowPrompt)}
            </div>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, minmax(0, 1fr))', gap: 9 }}>
            {s.arrows.map((item, i) => (
              <div key={i} style={{ borderRadius: 12, background: c.surfaceAlt, border: `1px solid ${c.border}`, padding: '10px 4px', textAlign: 'center' }}>
                <div style={{ fontSize: 13, fontWeight: 800, color: c.text, marginBottom: 2 }}>{item[0]}</div>
                <div style={{ fontSize: 25, lineHeight: 1, color: c.accent }}>{item[1] === 'left' ? '←' : '→'}</div>
              </div>
            ))}
          </div>
        </div>

        <div style={{ ...asfCard(c), padding: '13px 15px' }}>
          <p style={{ margin: 0, fontSize: 15, lineHeight: 1.45, color: c.text }}>{c.L(s.arrowQuestion)}</p>
          <AnswerField base={`${base}_arrow_q`} />
        </div>

        <div style={{ ...asfCard(c), padding: '14px 14px 15px' }}>
          <div style={{ display: 'flex', gap: 9, alignItems: 'baseline', marginBottom: 12 }}>
            <div style={{ fontFamily: c.headingStack, fontWeight: 900, color: c.accent, minWidth: 22 }}>d.</div>
            <div style={{ fontSize: 15, color: c.text, lineHeight: 1.4 }}>
              {c.L(s.wordPrompt)}
            </div>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, minmax(0, 1fr))', gap: 10 }}>
            {s.wordGrid.map((word, i) => {
              const mark = wordMarks[i] || '';
              return (
                <button key={i} onClick={() => cycleWord(i)} style={{
                  minHeight: 45, borderRadius: mark === 'circle' ? 999 : 9,
                  border: `2px solid ${mark ? c.accent : c.border}`,
                  background: mark ? c.surface : c.surfaceAlt, color: c.text, cursor: 'pointer',
                  fontFamily: "'Spectral', Georgia, serif", fontSize: 17, fontWeight: 700,
                }}>{word}</button>
              );
            })}
          </div>
        </div>
      </div>
    </div>
  );
}

function ShapeIcon({ type }) {
  const c = useTheme();
  const [shape, styleName] = (type || '').split('-');
  const id = React.useMemo(() => `pat_${Math.random().toString(36).slice(2)}`, []);
  const fill = styleName === 'fill' ? c.text : (styleName === 'lines' || styleName === 'dots' ? `url(#${id})` : 'transparent');
  const stroke = styleName === 'fill' ? c.text : c.text;
  const shapeProps = { fill, stroke, strokeWidth: 2 };
  return (
    <svg width="35" height="35" viewBox="0 0 36 36" aria-hidden="true" style={{ flexShrink: 0 }}>
      <defs>
        <pattern id={id} width="7" height="7" patternUnits="userSpaceOnUse">
          {styleName === 'dots'
            ? <circle cx="2.5" cy="2.5" r="1.6" fill={c.text} />
            : <path d="M0 2h7M0 5h7" stroke={c.text} strokeWidth="1.4" />}
        </pattern>
      </defs>
      {shape === 'circle' && <circle cx="18" cy="18" r="13" {...shapeProps} />}
      {shape === 'triangle' && <polygon points="18,4 32,31 4,31" {...shapeProps} />}
      {shape === 'diamond' && <polygon points="18,3 33,18 18,33 3,18" {...shapeProps} />}
      {(!shape || shape === 'square' || !['circle','triangle','diamond'].includes(shape)) && <rect x="5" y="5" width="26" height="26" {...shapeProps} />}
    </svg>
  );
}

function WritingBlock({ s, base }) {
  const c = useTheme();
  const [val, setVal] = useLocal(base, '');
  return (
    <div>
      <ActLabel>{c.L(s.label)}</ActLabel>
      <p style={{ margin: '0 0 12px', fontSize: 15, lineHeight: 1.5, color: c.textMuted }}>{c.L(s.prompt)}</p>
      <textarea value={val} onChange={e => setVal(e.target.value)} placeholder={c.t('act_optional')} rows={7} style={{
        width: '100%', boxSizing: 'border-box', resize: 'none', borderRadius: 13, padding: '15px', lineHeight: 1.7,
        border: `1px dashed ${c.border}`, background: c.surfaceAlt, color: c.text, fontFamily: c.headingStack, fontSize: 16, outline: 'none',
      }} />
    </div>
  );
}

function PhrasePairsBlock({ s, base }) {
  const c = useTheme();
  const [vals, setVals] = useLocal(base, {});
  const setVal = (key, value) => setVals(v => ({ ...v, [key]: value }));
  return (
    <div>
      <ActLabel>{c.L(s.label)}</ActLabel>
      <p style={{ margin: '0 0 14px', fontSize: 15.5, lineHeight: 1.55, color: c.text }}>{c.L(s.prompt)}</p>
      <div style={{ ...asfCard(c), padding: '13px 15px', marginBottom: 10 }}>
        <div style={{ display: 'grid', gridTemplateColumns: '88px 1fr 1fr', gap: 10, alignItems: 'center' }}>
          <div style={{ fontWeight: 900, color: c.accent }}>a. {s.example.word}:</div>
          <div style={{ fontFamily: "'Spectral', Georgia, serif", fontSize: 16, color: c.text }}>{s.example.visible}</div>
          <div style={{ fontFamily: "'Spectral', Georgia, serif", fontSize: 16, color: c.text }}>{s.example.invisible}</div>
        </div>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {s.words.map((word, i) => {
          const letter = String.fromCharCode(98 + i);
          return (
            <div key={word} style={{ ...asfCard(c), padding: '13px 15px' }}>
              <div style={{ fontWeight: 900, color: c.accent, marginBottom: 8 }}>{letter}. {word}:</div>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 9 }}>
                <input value={vals[`${word}_visible`] || ''} onChange={e => setVal(`${word}_visible`, e.target.value)} placeholder="seen" style={phraseInputStyle(c)} />
                <input value={vals[`${word}_invisible`] || ''} onChange={e => setVal(`${word}_invisible`, e.target.value)} placeholder="not seen" style={phraseInputStyle(c)} />
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function phraseInputStyle(c) {
  return {
    width: '100%', boxSizing: 'border-box', border: `1px dashed ${c.border}`, background: c.surfaceAlt,
    color: c.text, borderRadius: 10, padding: '10px 11px', fontFamily: 'inherit', fontSize: 14.5, outline: 'none',
  };
}

Object.assign(window, { useLocal, QuestionsBlock, ChoiceBlock, WordbankBlock, FillbankBlock, AttentionBlock, PhrasePairsBlock, WritingBlock });
