// kiosk.jsx — the door tablet: attract → tap → activity picker → confirm; tap-to-sign-out; manual.
const { useState: kUseState, useMemo: kUseMemo, useEffect: kUseEffect, useRef: kUseRef } = React;

function Kiosk({ activities, present, students, onSignIn, onSignOut, location, locationId = 'workshop' }) {
  const { Icon, Avatar, useNow } = window;
  const now = useNow(1000);
  const [screen, setScreen] = kUseState('attract'); // attract | greet | success | manual | pin
  const [curId, setCurId] = kUseState(null);
  const [pendingId, setPendingId] = kUseState(null); // student awaiting code entry
  const [last, setLast] = kUseState(null); // {type, student, activity, inE, outMs}
  const [q, setQ] = kUseState('');
  const proceedRef = kUseRef(null);

  const presentMap = kUseMemo(() => {
    const m = {};
    present.forEach((p) => (m[p.studentId] = p));
    return m;
  }, [present]);

  const cur = curId ? students.find((s) => s.id === curId) : null;
  const actById = kUseMemo(() => Object.fromEntries(activities.map((a) => [a.id, a])), [activities]);

  // auto-return to attract after a success screen
  kUseEffect(() => {
    if (screen !== 'success') return;
    const t = setTimeout(() => goAttract(), 6000);
    return () => clearTimeout(t);
  }, [screen, last]);

  function goAttract() { setScreen('attract'); setCurId(null); setQ(''); }

  // proceed = the actual sign-in/out branch. Used directly by RFID tag taps (the tag
  // is the credential). The by-name path runs this only after the code is verified.
  function proceed(studentId) {
    const here = presentMap[studentId];
    const s = students.find((x) => x.id === studentId);
    if (here) {
      // present → sign out
      const outMs = Date.now() - here.inE;
      onSignOut(studentId);
      setLast({ type: 'out', student: s, activity: actById[here.activity], inE: here.inE, outMs });
      setScreen('success');
    } else {
      setCurId(studentId);
      setScreen('greet');
    }
  }
  proceedRef.current = proceed;

  // RFID reader agents publish kiosk-safe student scan events through the server.
  kUseEffect(() => {
    const source = new EventSource(`/api/kiosk/events?location=${encodeURIComponent(locationId)}`);
    const onStudentScan = event => {
      try {
        const scan = JSON.parse(event.data);
        if (scan.studentId && proceedRef.current) proceedRef.current(scan.studentId);
      } catch (error) {
        console.error('Invalid RFID scan event:', error);
      }
    };

    source.addEventListener('student-scan', onStudentScan);
    source.onerror = () => console.warn('RFID event stream disconnected; retrying automatically.');

    return () => {
      source.removeEventListener('student-scan', onStudentScan);
      source.close();
    };
  }, [locationId]);

  // by-name path: ask for the personal code first
  function askCode(studentId) { setPendingId(studentId); setScreen('pin'); }
  function onCodeOk() { const id = pendingId; setPendingId(null); proceed(id); }

  async function choose(activityIds) {
    const selectedIds = Array.isArray(activityIds) ? activityIds : [activityIds];
    await onSignIn(curId, selectedIds.length === 1 ? selectedIds[0] : selectedIds);
    setLast({
      type: 'in',
      student: cur,
      activity: actById[selectedIds[0]],
      activities: selectedIds.map(id => actById[id]).filter(Boolean),
      inE: Date.now()
    });
    setScreen('success');
  }

  const clockT = new Date(now).toLocaleTimeString('en-AU', { hour: 'numeric', minute: '2-digit', hour12: true });
  const clockD = new Date(now).toLocaleDateString('en-AU', { weekday: 'long', day: 'numeric', month: 'long' });

  return (
    <div className="kiosk">
      <div className="kiosk-grid"></div>

      <div className="kiosk-top">
        <img src="assets/logo-robot.png" className="pixel" alt="" />
        <span className="word">BotBuilders</span>
        <span className="where">{location || 'Workshop · 459 Newman Rd'}</span>
        <div className="kiosk-clock">
          <div className="t">{clockT}</div>
          <div className="d">{clockD}</div>
        </div>
      </div>

      {screen === 'attract' && <Attract present={present} onManual={() => setScreen('manual')} />}
      {screen === 'greet' && cur && (
        <Greet s={cur} activities={activities} onChoose={choose} onCancel={goAttract} />
      )}
      {screen === 'success' && last && (
        <Success last={last} onDone={goAttract} now={now} />
      )}
      {screen === 'manual' && (
        <Manual students={students} presentMap={presentMap} q={q} setQ={setQ} onPick={askCode} onCancel={goAttract} />
      )}
      {screen === 'pin' && pendingId && (
        <PinPad student={students.find((s) => s.id === pendingId)} onOk={onCodeOk} onCancel={() => { setPendingId(null); setScreen('manual'); }} />
      )}

      {/* footer count — hidden on greet/manual to keep focus */}
      {screen === 'attract' && (
        <div className="kiosk-foot">
          <span className="count-chip"><span className="dot"></span><b>{present.length}</b>&nbsp;builders in the workshop</span>
          <button className="linkbtn" onClick={() => setScreen('manual')}>
            <Icon name="search" size={16} /> No tag? Sign in by name
          </button>
        </div>
      )}

    </div>
  );
}

function Attract({ present, onManual }) {
  return (
    <div className="kiosk-body attract fade">
      <div className="reader">
        <span className="ring"></span>
        <img src="assets/logo-robot.png" className="pixel" alt="" />
      </div>
      <h1>Tap your tag to <span className="b">sign in</span></h1>
      <p>Hold your BotBuilders tag to the reader to clock in &mdash; or out.</p>
    </div>
  );
}

function Greet({ s, activities, onChoose, onCancel }) {
  const { Avatar, Icon } = window;
  const [selected, setSelected] = kUseState([]);
  const [loading, setLoading] = kUseState(false);
  const [error, setError] = kUseState('');
  const enrolledIds = new Set(s.enrolled);
  // enrolled first, then the rest as "other activity"
  const enrolled = activities.filter((a) => enrolledIds.has(a.id));
  const others = activities.filter((a) => !enrolledIds.has(a.id));
  const list = [...enrolled, ...others];

  async function selectActivity(activityId) {
    if (loading) return;
    if (list.length === 1) {
      setLoading(true);
      try {
        await onChoose(activityId);
      } catch (submitError) {
        setError('Could not sign you in. Please try again.');
        setLoading(false);
      }
      return;
    }

    setError('');
    setSelected(current => current.includes(activityId)
      ? current.filter(id => id !== activityId)
      : [...current, activityId]);
  }

  async function confirmSelection() {
    if (selected.length === 0 || loading) return;
    setLoading(true);
    setError('');
    try {
      await onChoose(selected);
    } catch (submitError) {
      setError('Could not sign you in. Please try again.');
      setLoading(false);
    }
  }

  return (
    <div className="kiosk-body fade">
      <div className="greet">
        <div className="greet-head">
          <Avatar s={s} />
          <div>
            <h1>Hi {s.name.split(' ')[0]}!</h1>
            <p className="sub">What are you here for today?</p>
          </div>
        </div>
        <div className="act-grid" style={{ marginTop: 18 }}>
          {list.map((a) => {
            const isEnrolled = enrolledIds.has(a.id);
            const isSelected = selected.includes(a.id);
            return (
              <button
                key={a.id}
                className={'act-btn' + (isEnrolled ? ' enrolled' : ' act-other') + (isSelected ? ' selected' : '')}
                onClick={() => selectActivity(a.id)}
                disabled={loading}
              >
                <span className="act-ic" style={{ background: a.color }}><Icon name={a.icon} size={22} style={{ color: '#fff' }} /></span>
                <span className="nm">{a.short_name || a.short || a.name}</span>
                <span className="mt">{isEnrolled ? 'Your activity' : a.code}</span>
                {isSelected && <span className="corner"><Icon name="check" size={20} /></span>}
              </button>
            );
          })}
        </div>
        {error && <div className="pin-err" style={{ marginTop: 14 }}>{error}</div>}
        <div className="greet-actions">
          <button className="linkbtn" onClick={onCancel} disabled={loading}>
            <Icon name="x" size={16} /> That&rsquo;s not me / cancel
          </button>
          {list.length > 1 && (
            <button className="kbtn" onClick={confirmSelection} disabled={selected.length === 0 || loading}>
              <Icon name={loading ? 'loader' : 'log-in'} size={18} />
              {loading ? 'Signing in...' : `Sign in${selected.length ? ` (${selected.length})` : ''}`}
            </button>
          )}
        </div>
      </div>
    </div>
  );
}

function Success({ last, onDone, now }) {
  const { Avatar, Icon } = window;
  const isIn = last.type === 'in';
  const color = isIn ? 'var(--success)' : 'var(--bb-blue)';
  return (
    <div className="kiosk-body success fade">
      <div className="burst" style={{ background: isIn ? 'var(--bb-blue-tint)' : '#fff' }}>
        <img src="assets/logo-robot.png" className="pixel" alt="" />
      </div>
      <h1>{isIn ? `You\u2019re in, ${last.student.name.split(' ')[0]}!` : `See you later, ${last.student.name.split(' ')[0]}!`}</h1>
      {isIn ? (
        <span className="line">
          <Icon name="log-in" size={18} style={{ color: 'var(--success)' }} />
          Signed in to <b style={{ color: last.activity.color }}>&nbsp;{(last.activities || [last.activity]).map(a => a.short_name || a.short || a.name).join(', ')}</b>&nbsp;at {window.fmtTime(last.inE)}
        </span>
      ) : (
        <span className="line">
          <Icon name="clock" size={18} style={{ color: 'var(--bb-blue-dark)' }} />
          You were here <b>&nbsp;{window.fmtDur(last.outMs)}&nbsp;</b> today
        </span>
      )}
      <button className="kbtn" onClick={onDone}>
        <Icon name="check" size={20} style={{ color: '#fff' }} /> Done
      </button>
      <div className="hint">Returning to the home screen&hellip;</div>
    </div>
  );
}

function Manual({ students, presentMap, q, setQ, onPick, onCancel }) {
  const { Avatar, Icon } = window;
  const ql = q.trim().toLowerCase();
  const list = students
    .filter((s) => !ql || s.name.toLowerCase().includes(ql))
    .slice(0, 12);
  return (
    <div className="kiosk-body fade">
      <div className="manual">
        <button className="linkbtn" style={{ marginBottom: 8, marginLeft: -10 }} onClick={onCancel}>
          <Icon name="arrow-left" size={16} /> Back
        </button>
        <h1>Find your name</h1>
        <p className="sub">Forgot your tag? No worries &mdash; pick your name, then enter your personal code.</p>
        <div className="search">
          <Icon name="search" size={20} style={{ color: 'var(--fg3)' }} />
          <input autoFocus value={q} onChange={(e) => setQ(e.target.value)} placeholder="Start typing your name…" />
        </div>
        <div className="name-list">
          {list.map((s) => {
            const here = presentMap[s.id];
            return (
              <button key={s.id} className={'name-row' + (here ? ' present' : '')} onClick={() => onPick(s.id)}>
                <Avatar s={s} />
                <div>
                  <div className="nm">{s.name}</div>
                  <div className="mt">Yr {s.grade}</div>
                </div>
                <span className="pin">
                  {here
                    ? <span className="via" style={{ color: 'var(--success)' }}><Icon name="log-out" size={15} /> Sign out</span>
                    : <Icon name="chevron-right" size={18} style={{ color: 'var(--n300)' }} />}
                </span>
              </button>
            );
          })}
          {list.length === 0 && <div className="empty" style={{ gridColumn: '1 / -1' }}>No builders match &ldquo;{q}&rdquo;</div>}
        </div>
      </div>
    </div>
  );
}

function PinPad({ student, onOk, onCancel }) {
  const { Avatar, Icon } = window;
  const [val, setVal] = kUseState('');
  const [err, setErr] = kUseState(false);
  const [verifying, setVerifying] = kUseState(false);
  const first = student.name.split(' ')[0];

  async function push(d) {
    if (verifying) return;
    if (err) setErr(false);
    if (val.length >= 4) return;
    const nv = val + d;
    setVal(nv);
    if (nv.length === 4) {
      setVerifying(true);
      try {
        const isValid = window.apiAdapter && await window.apiAdapter.verifyPin(student.id, nv);
        if (isValid) {
          setTimeout(onOk, 180);
        } else {
          setTimeout(() => { setErr(true); setVal(''); setVerifying(false); }, 220);
        }
      } catch (error) {
        console.error('PIN verification error:', error);
        setTimeout(() => { setErr(true); setVal(''); setVerifying(false); }, 220);
      }
    }
  }
  function del() {
    if (verifying) return;
    setErr(false);
    setVal((v) => v.slice(0, -1));
  }

  return (
    <div className="kiosk-body fade">
      <div className="pinpad">
        <button className="linkbtn" style={{ marginBottom: 6, marginLeft: -10 }} onClick={onCancel}>
          <Icon name="arrow-left" size={16} /> Back
        </button>
        <div className="pin-head">
          <Avatar s={student} />
          <div>
            <h1>Enter your code</h1>
            <p className="sub">Hi {first}! Type your 4-digit code so we know it&rsquo;s really you.</p>
          </div>
        </div>
        <div className={'pin-dots' + (err ? ' err' : '')}>
          {[0, 1, 2, 3].map((i) => <span key={i} className={'pin-dot' + (val.length > i ? ' on' : '')}></span>)}
        </div>
        <div className="pin-err" style={{ visibility: err ? 'visible' : 'hidden' }}>
          <Icon name="x" size={14} /> Wrong code &mdash; give it another go
        </div>
        <div className="keypad">
          {['1', '2', '3', '4', '5', '6', '7', '8', '9'].map((k) => (
            <button key={k} className="key" onClick={() => push(k)}>{k}</button>
          ))}
          <button className="key ghost" onClick={onCancel} aria-label="Cancel"><Icon name="x" size={22} /></button>
          <button className="key" onClick={() => push('0')}>0</button>
          <button className="key ghost" onClick={del} aria-label="Delete"><Icon name="delete" size={22} /></button>
        </div>
      </div>
    </div>
  );
}


window.Kiosk = Kiosk;
