// PAPI Kostick psychometric test — list, take (90 forced-choice items), result.
// Backend: /api/papi (meta, list, create, get, patch autosave, submit).

function PapiView({ go, state }) {
  if (state.testId) return <PapiRunner testId={state.testId} go={go} />;
  return <PapiList go={go} candidateId={state.candidateId} />;
}

// ── List + create ──────────────────────────────────────────────────────────
function PapiList({ go, candidateId }) {
  const { CANDIDATES } = window.TalentirData;
  const [tests, setTests] = useState(null);
  const [showNew, setShowNew] = useState(!!candidateId);

  const load = () => window.TalentirAPI.get('/api/papi').then(setTests).catch(() => setTests([]));
  useEffect(() => { load(); }, []);

  return (
    <div className="view">
      <div className="view-head">
        <div>
          <div className="title">Psikotes — PAPI Kostick</div>
          <div className="subtitle">Personality and Preference Inventory · 90 soal · skor 20 faktor kepribadian, dikelompokkan per aspek.</div>
        </div>
        <Btn kind="accent" icon="plus" onClick={() => setShowNew(true)}>Tes Baru</Btn>
      </div>

      {!tests && <div className="empty">Memuat…</div>}
      {tests && tests.length === 0 && (
        <div className="card empty" style={{ padding: 40 }}>
          <Icon name="sparkles" size={26}/>
          <div style={{ fontWeight: 700, marginTop: 10 }}>Belum ada tes</div>
          <div style={{ marginTop: 4 }}>Mulai tes PAPI baru untuk seorang kandidat.</div>
        </div>
      )}
      {tests && tests.length > 0 && (
        <div className="card" style={{ overflow: 'hidden' }}>
          <table className="tbl">
            <thead><tr><th>Nama</th><th>No. Tes</th><th>Tanggal</th><th>Status</th><th style={{ width: 90 }}></th></tr></thead>
            <tbody>
              {tests.map(t => (
                <tr key={t.id} style={{ cursor: 'pointer' }} onClick={() => go({ view: 'papi', testId: t.id })}>
                  <td><div className="row-flex"><Avatar name={t.nama}/><strong>{t.nama}</strong></div></td>
                  <td className="mono" style={{ fontSize: 12 }}>{t.noTes}</td>
                  <td style={{ fontSize: 12.5 }}>{t.tanggalTes}</td>
                  <td><Badge kind={t.status === 'completed' ? 'good' : 'warn'}><span className="dot"/>{t.status === 'completed' ? 'Selesai' : 'Draft'}</Badge></td>
                  <td><Btn size="sm">{t.status === 'completed' ? 'Hasil →' : 'Lanjut →'}</Btn></td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      {showNew && <NewPapiModal candidates={CANDIDATES} defaultCandidate={candidateId} onClose={() => setShowNew(false)}
        onCreated={(t) => { setShowNew(false); go({ view: 'papi', testId: t.id }); }}/>}
    </div>
  );
}

function NewPapiModal({ candidates, defaultCandidate, onClose, onCreated }) {
  const [f, setF] = useState({ candidateId: defaultCandidate || '', nama: '', tanggalLahir: '', tujuan: 'Rekrutmen' });
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState(null);
  const set = (k) => (e) => { setF(s => ({ ...s, [k]: e.target.value })); setError(null); };
  const cand = candidates.find(c => c.id === f.candidateId);

  const create = async () => {
    setSaving(true); setError(null);
    try {
      const t = await window.TalentirAPI.post('/api/papi', {
        candidateId: f.candidateId || null,
        nama: f.nama || undefined,
        tanggalLahir: f.tanggalLahir || null,
        tujuan: f.tujuan,
      });
      onCreated(t);
    } catch (e) {
      console.error(e);
      setError(e?.message || 'Gagal membuat tes PAPI. Coba lagi.');
      setSaving(false);
    }
  };

  return (
    <div className="modal-scrim" onClick={onClose}>
      <div className="modal" style={{ width: 480 }} onClick={(e) => e.stopPropagation()}>
        <div className="modal-head"><h3 style={{ margin: 0, fontSize: 16 }}>Tes PAPI Baru</h3><div style={{ flex: 1 }}/><button className="btn icon ghost" onClick={onClose}><Icon name="x" size={14}/></button></div>
        <div className="modal-body col-flex" style={{ gap: 12 }}>
          <div className="field"><label>Kandidat (opsional)</label>
            <select className="select" value={f.candidateId} onChange={set('candidateId')}>
              <option value="">— Klien manual —</option>
              {candidates.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
            </select>
          </div>
          <div className="field"><label>Nama {cand ? '(dari kandidat)' : ''}</label>
            <input className="input" value={f.nama || (cand ? cand.name : '')} onChange={set('nama')} placeholder="Nama peserta" disabled={!!cand}/>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
            <div className="field"><label>Tanggal lahir</label><input className="input" type="date" value={f.tanggalLahir} onChange={set('tanggalLahir')}/></div>
            <div className="field"><label>Tujuan</label>
              <select className="select" value={f.tujuan} onChange={set('tujuan')}>
                <option>Rekrutmen</option><option>Pengembangan / dll</option><option>Promosi</option>
              </select>
            </div>
          </div>
        </div>
        {error && (
          <div style={{ margin: '0 18px 12px', background: 'oklch(0.96 0.04 25)', border: '1px solid oklch(0.78 0.12 25)', color: 'oklch(0.4 0.15 25)', padding: '8px 12px', borderRadius: 7, fontSize: 12 }}>
            ⚠ {error}
          </div>
        )}
        <div className="modal-foot">
          <Btn onClick={onClose}>Batal</Btn>
          <Btn kind="accent" icon="check" onClick={create} disabled={saving || (!f.candidateId && !f.nama.trim())}>{saving ? 'Membuat…' : 'Mulai Tes'}</Btn>
        </div>
      </div>
    </div>
  );
}

// ── Runner: loads a test, shows form (draft) or result (completed) ───────────
function PapiRunner({ testId, go }) {
  const [test, setTest] = useState(null);
  const [err, setErr] = useState(null);
  const reload = () => window.TalentirAPI.get('/api/papi/' + testId).then(setTest).catch(() => setErr('Gagal memuat tes.'));
  useEffect(() => { reload(); }, [testId]);

  if (err) return <div className="view"><div className="empty">{err}</div></div>;
  if (!test) return <div className="view"><div className="empty">Memuat tes…</div></div>;
  return (
    <div className="view">
      <div style={{ marginBottom: 12 }}>
        <button className="btn ghost sm" onClick={() => go({ view: 'papi' })}><Icon name="arrowL" size={12}/> Semua Tes</button>
      </div>
      {test.status === 'completed'
        ? <PapiResult test={test}/>
        : <PapiForm test={test} onSubmitted={(t) => setTest(t)}/>}
    </div>
  );
}

// ── The 90-item test form ────────────────────────────────────────────────────
const TOTAL_Q = 90;
function PapiForm({ test, onSubmitted }) {
  const [answers, setAnswers] = useState(test.answers || {});
  const [seconds, setSeconds] = useState(test.durationSec || 0);
  const [submitting, setSubmitting] = useState(false);
  const [err, setErr] = useState(null);
  const saveTimer = useRef(null);
  const answersRef = useRef(answers);
  answersRef.current = answers;

  // Timer (counts up while taking the test).
  useEffect(() => {
    const t = setInterval(() => setSeconds(s => s + 1), 1000);
    return () => clearInterval(t);
  }, []);

  // Debounced auto-save of answers + duration.
  const queueSave = () => {
    clearTimeout(saveTimer.current);
    saveTimer.current = setTimeout(() => {
      window.TalentirAPI.patch('/api/papi/' + test.id, { answers: answersRef.current, durationSec: seconds }).catch(() => {});
    }, 900);
  };

  const pick = (q, opt) => { setAnswers(a => ({ ...a, [q]: opt })); queueSave(); };

  const answered = Object.keys(answers).filter(q => answers[q] === 'a' || answers[q] === 'b').length;
  const pct = Math.round((answered / TOTAL_Q) * 100);
  const fmt = (s) => `${Math.floor(s / 60)}:${String(s % 60).padStart(2, '0')}`;
  const firstUnanswered = () => { for (let q = 1; q <= TOTAL_Q; q++) if (!answers[q]) return q; return null; };

  const submit = async () => {
    setErr(null);
    if (answered < TOTAL_Q) { setErr(`Masih ada ${TOTAL_Q - answered} soal belum dijawab.`); jumpTo(firstUnanswered()); return; }
    if (!window.confirm('Submit jawaban? Skor akan dihitung dan tidak bisa diubah lagi.')) return;
    setSubmitting(true);
    try {
      const t = await window.TalentirAPI.post('/api/papi/' + test.id + '/submit', { answers, durationSec: seconds });
      onSubmitted(t);
    } catch (e) {
      setErr(e.message && e.message.includes('400') ? 'Belum lengkap.' : 'Gagal submit.');
      setSubmitting(false);
    }
  };

  const jumpTo = (q) => { if (q) { const el = document.getElementById('q-' + q); if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' }); } };

  return (
    <>
      <div className="view-head" style={{ marginBottom: 14 }}>
        <div>
          <div className="title" style={{ fontSize: 22 }}>{test.nama}</div>
          <div className="subtitle">{test.noTes} · {test.tujuan || '—'} {test.usia != null ? `· ${test.usia} th` : ''}</div>
        </div>
        <div className="row-flex">
          <Badge><Icon name="clock" size={11}/> {fmt(seconds)}</Badge>
          <Btn kind="accent" icon="check" onClick={submit} disabled={submitting}>{submitting ? 'Menghitung…' : `Submit (${answered}/${TOTAL_Q})`}</Btn>
        </div>
      </div>

      {/* Sticky progress */}
      <div style={{ position: 'sticky', top: 0, zIndex: 2, background: 'var(--bg)', paddingBottom: 8 }}>
        <div className="row-flex" style={{ marginBottom: 6 }}>
          <span style={{ fontSize: 12.5, color: 'var(--muted)' }}>{answered}/{TOTAL_Q} terjawab</span>
          {answered < TOTAL_Q && <button className="btn ghost sm" onClick={() => jumpTo(firstUnanswered())}>Ke soal belum terisi →</button>}
          <div style={{ flex: 1 }}/>
          {err && <span style={{ color: 'oklch(0.55 0.18 25)', fontSize: 12.5, fontWeight: 600 }}>{err}</span>}
        </div>
        <div style={{ height: 6, background: 'var(--surface-2)', borderRadius: 99, overflow: 'hidden' }}>
          <div style={{ width: pct + '%', height: '100%', background: 'var(--accent)', transition: 'width .2s' }}/>
        </div>
      </div>

      <div className="card card-pad" style={{ marginTop: 12, fontSize: 12.5, color: 'var(--ink-2)', background: 'var(--bg-soft)' }}>
        Pilih <strong>A</strong> atau <strong>B</strong> sesuai jawaban peserta untuk tiap nomor pada buku soal PAPI. Jawaban tersimpan otomatis.
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(150px, 1fr))', gap: 8, marginTop: 12 }}>
        {Array.from({ length: TOTAL_Q }, (_, i) => i + 1).map(q => {
          const v = answers[q];
          return (
            <div key={q} id={'q-' + q} className="card" style={{ padding: '8px 10px', borderColor: v ? 'var(--border)' : 'oklch(0.85 0.06 25)' }}>
              <div className="row-flex" style={{ gap: 8 }}>
                <span className="mono" style={{ fontWeight: 700, fontSize: 12, width: 22, color: 'var(--muted)' }}>{q}</span>
                {['a', 'b'].map(opt => (
                  <button key={opt} onClick={() => pick(q, opt)}
                    style={{
                      flex: 1, padding: '5px 0', borderRadius: 6, fontWeight: 700, fontSize: 13, cursor: 'pointer',
                      border: '1px solid ' + (v === opt ? 'var(--accent)' : 'var(--border)'),
                      background: v === opt ? 'var(--accent)' : 'var(--surface)',
                      color: v === opt ? 'white' : 'var(--ink-2)',
                    }}>{opt.toUpperCase()}</button>
                ))}
              </div>
            </div>
          );
        })}
      </div>

      <div className="row-flex" style={{ justifyContent: 'flex-end', marginTop: 18 }}>
        <Btn kind="accent" icon="check" onClick={submit} disabled={submitting}>{submitting ? 'Menghitung…' : `Submit (${answered}/${TOTAL_Q})`}</Btn>
      </div>
    </>
  );
}

// ── Result: psikogram (bars per aspect) + totals + interpretation + PDF ──────
function PapiResult({ test }) {
  const r = test.result;
  const interp = test.interpretation || [];
  const interpByCode = Object.fromEntries(interp.map(i => [i.code, i]));
  const bandColor = (b) => b === 'tinggi' ? 'oklch(0.58 0.13 155)' : b === 'rendah' ? 'oklch(0.60 0.16 25)' : 'oklch(0.55 0.05 260)';

  return (
    <div className="papi-result">
      <div className="view-head" style={{ marginBottom: 14 }}>
        <div>
          <div className="title" style={{ fontSize: 22 }}>Psikogram — {test.nama}</div>
          <div className="subtitle">{test.noTes} · {test.tanggalTes} {test.usia != null ? `· ${test.usia} th` : ''} · durasi {Math.floor((test.durationSec||0)/60)} mnt</div>
        </div>
        <Btn icon="download" onClick={() => window.print()}>Cetak / PDF</Btn>
      </div>

      {/* Validation banner */}
      <div className="card card-pad" style={{ marginBottom: 16, display: 'flex', gap: 20, alignItems: 'center', flexWrap: 'wrap' }}>
        <div><div style={{ fontSize: 11, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: '.06em', fontWeight: 700 }}>Total Atas</div><div className="mono" style={{ fontSize: 22, fontWeight: 800 }}>{r.totalAtas}<span style={{ color: 'var(--muted)', fontSize: 14 }}>/45</span></div></div>
        <div><div style={{ fontSize: 11, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: '.06em', fontWeight: 700 }}>Total Bawah</div><div className="mono" style={{ fontSize: 22, fontWeight: 800 }}>{r.totalBawah}<span style={{ color: 'var(--muted)', fontSize: 14 }}>/45</span></div></div>
        <div style={{ flex: 1 }}/>
        <Badge kind={r.balanced ? 'good' : 'warn'}><span className="dot"/>{r.balanced ? 'Validasi seimbang (45/45)' : 'Belum 45/45 — periksa kunci skoring resmi'}</Badge>
      </div>

      {/* Psikogram bars grouped by aspect */}
      <div className="card card-pad">
        <div className="section-title" style={{ marginBottom: 12 }}>Profil per Faktor (skor 0–9)</div>
        {Object.entries(r.byAspect).map(([aspect, factors]) => (
          <div key={aspect} style={{ marginBottom: 16 }}>
            <div style={{ fontSize: 11.5, fontWeight: 700, color: 'var(--accent-ink)', textTransform: 'uppercase', letterSpacing: '.06em', marginBottom: 8 }}>{aspect}</div>
            <div className="col-flex" style={{ gap: 7 }}>
              {factors.map(f => {
                const ip = interpByCode[f.code];
                return (
                  <div key={f.code} style={{ display: 'grid', gridTemplateColumns: '230px 1fr 30px', gap: 10, alignItems: 'center', fontSize: 13 }}>
                    <div style={{ color: 'var(--ink-2)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                      <span className="mono" style={{ fontWeight: 700, marginRight: 6, color: 'var(--muted)' }}>{f.code}</span>{f.name}
                    </div>
                    <div style={{ display: 'flex', gap: 2 }}>
                      {Array.from({ length: 9 }, (_, i) => (
                        <div key={i} style={{ flex: 1, height: 16, borderRadius: 2, background: i < f.score ? bandColor(ip?.band) : 'var(--surface-2)' }}/>
                      ))}
                    </div>
                    <div className="mono" style={{ textAlign: 'right', fontWeight: 700 }}>{f.score}</div>
                  </div>
                );
              })}
            </div>
          </div>
        ))}
      </div>

      {/* Interpretation */}
      <div className="card card-pad" style={{ marginTop: 16 }}>
        <div className="section-title" style={{ marginBottom: 10 }}>Interpretasi</div>
        <div className="col-flex" style={{ gap: 6 }}>
          {interp.map(i => (
            <div key={i.code} className="row-flex" style={{ fontSize: 13 }}>
              <Badge kind={i.band === 'tinggi' ? 'good' : i.band === 'rendah' ? 'danger' : ''} style={{ minWidth: 64, justifyContent: 'center' }}>{i.band}</Badge>
              <span style={{ color: 'var(--ink-2)' }}>{i.text}</span>
            </div>
          ))}
        </div>
        <div style={{ fontSize: 11.5, color: 'var(--muted)', marginTop: 12 }}>
          Interpretasi ringkas berbasis band skor. Untuk narasi mendalam, gunakan panduan PAPI resmi.
        </div>
      </div>
    </div>
  );
}

window.PapiView = PapiView;
