/* Brand Lens — calibration loop: the AI calls it FIRST, you react and say why.
   Your comment is the signal; one Agree/Disagree tap captures convergence. */
function Review({ recs, reload, goLibrary, goScore, layout, setLayout }) {
  const buildQueue = useCallback(
    () => recs.filter((r) => !r.user).sort((a, b) => a.shuffleKey - b.shuffleKey).map((r) => r.id),
    [recs]
  );
  const [queue, setQueue] = useState(buildQueue);
  const [pos, setPos] = useState(0);
  const [agree, setAgree] = useState(null);     // true = AI got it right, false = wrong
  const [comment, setComment] = useState('');
  const [category, setCategory] = useState('auto');
  const [aiState, setAiState] = useState('idle');  // idle|loading|ready|error
  const [submitting, setSubmitting] = useState(false);
  const [retryTick, setRetryTick] = useState(0);   // bump to re-run analysis after an error
  const aiCache = useRef({});                        // 'id|cat' -> verdict

  const recById = useMemo(() => Object.fromEntries(recs.map((r) => [r.id, r])), [recs]);
  const currentId = queue[pos];
  const rec = currentId ? recById[currentId] : null;
  const done = pos >= queue.length;
  const catKey = (id, cat) => id + '|' + cat;

  useEffect(() => { if (rec) setCategory(rec.category || 'auto'); /* eslint-disable-next-line */ }, [currentId]);

  // analyze current image (shown immediately) for the chosen category; prefetch next
  useEffect(() => {
    let cancelled = false;
    async function ensure(id, cat, isCurrent) {
      if (!id) return;
      const r = recById[id]; if (!r) return;
      const key = catKey(id, cat);
      if (aiCache.current[key]) { if (isCurrent) setAiState('ready'); return; }
      if (r.ai && (r.ai.declared || 'auto') === cat) { aiCache.current[key] = r.ai; if (isCurrent) setAiState('ready'); return; }
      if (isCurrent) setAiState('loading');
      try {
        const v = await window.Lens.analyzeImage(r, cat === 'auto' ? null : cat);
        if (cancelled) return;
        aiCache.current[key] = v;
        if (isCurrent) await window.LensDB.patch(id, { ai: v, category: cat });
        if (isCurrent) setAiState('ready');
      } catch (e) {
        console.warn('analyze failed', e);
        if (isCurrent && !cancelled) setAiState('error');
      }
    }
    if (currentId) ensure(currentId, category, true);
    const nextId = queue[pos + 1];
    if (nextId) ensure(nextId, (recById[nextId] && recById[nextId].category) || 'auto', false);
    return () => { cancelled = true; };
    // eslint-disable-next-line
  }, [currentId, category, retryTick]);

  const ai = aiState === 'ready' ? aiCache.current[catKey(currentId, category)] : null;

  async function submit() {
    if (agree === null || !ai) return;
    setSubmitting(true);
    const aiKeep = ai.verdict === 'keep';
    const like = agree ? aiKeep : !aiKeep;     // derive the user's keep/reject from their reaction
    await window.LensDB.patch(currentId, {
      ai, category,
      user: { agree, like, comment: comment.trim(), reviewedAt: Date.now() },
    });
    await reload();
    setSubmitting(false);
    advance();
  }

  function advance() {
    setAgree(null); setComment(''); setAiState('idle');
    setPos((p) => p + 1);
  }
  function retry() { setAiState('idle'); setRetryTick((t) => t + 1); }
  function restart() {
    reload();
    const q = buildQueue();
    setQueue(q); setPos(0); setAgree(null); setComment(''); setAiState('idle');
  }

  if (done || queue.length === 0) {
    return (
      <div style={{ maxWidth: 620, margin: '40px auto', textAlign: 'center' }}>
        <div style={{ color: 'var(--st-success)', display: 'flex', justifyContent: 'center', marginBottom: 16 }}>
          <Icon name="check" size={48} stroke={2} />
        </div>
        <h2 style={{ fontSize: 30, fontWeight: 500, margin: 0 }}>
          {queue.length === 0 ? 'Nothing left to review' : 'Round complete'}
        </h2>
        <p style={{ fontSize: 16, color: 'var(--fg-2)', lineHeight: 1.6, margin: '14px 0 26px' }}>
          {queue.length === 0
            ? 'Add more images in the repository, or revisit your scoreboard and style guide.'
            : 'Now refresh the style guide — it re-teaches the judge from this round, so the next guesses come in closer.'}
        </p>
        <div style={{ display: 'flex', gap: 10, justifyContent: 'center', flexWrap: 'wrap' }}>
          <Btn kind="primary" icon="arrow" onClick={goScore}>See the scoreboard</Btn>
          <Btn icon="upload" onClick={goLibrary}>Back to repository</Btn>
          {recs.some((r) => !r.user) && <Btn kind="dark" onClick={restart}>Review more</Btn>}
        </div>
      </div>
    );
  }

  const total = queue.length;
  const panel = (
    <ReactPanel
      ai={ai} aiState={aiState} category={category} setCategory={setCategory}
      agree={agree} setAgree={setAgree} comment={comment} setComment={setComment}
      submit={submit} submitting={submitting} pos={pos} total={total} retry={retry} skip={advance}
    />
  );
  const imgCard = <ImageStage rec={rec} layout={layout} />;

  return (
    <div>
      <ReviewHeader pos={pos} total={total} layout={layout} setLayout={setLayout} />
      {layout === 'split' ? (
        <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0,1.25fr) minmax(360px,1fr)', gap: 26, alignItems: 'start' }}>
          {imgCard}
          <div style={{ position: 'sticky', top: 88 }}>{panel}</div>
        </div>
      ) : (
        <div style={{ maxWidth: 780, margin: '0 auto' }}>
          {imgCard}
          <div style={{ marginTop: 20 }}>{panel}</div>
        </div>
      )}
    </div>
  );
}

function ReviewHeader({ pos, total, layout, setLayout }) {
  const brief = window.Lens.getLearnedBrief();
  return (
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 16, marginBottom: 20, flexWrap: 'wrap' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
        <Icon name="scale" size={20} style={{ color: 'var(--ps-primary-blue)' }} />
        <div>
          <div style={{ fontSize: 18, fontWeight: 600, color: 'var(--ps-navy)' }}>Calibrate</div>
          <div style={{ fontSize: 13, color: 'var(--fg-3)' }}>
            Image {pos + 1} of {total} · the AI calls it first — you react and say why
          </div>
        </div>
      </div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
        {brief && (
          <span title={`The judge is calibrated from ${brief.basedOn} of your reviews`} style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12, fontWeight: 600,
            color: 'var(--ps-aqua-700)', background: 'var(--ps-aqua-100)', padding: '5px 11px', borderRadius: 60 }}>
            <Icon name="sparkle" size={13} /> Calibrated · {brief.basedOn}
          </span>
        )}
        <div style={{ display: 'flex', gap: 4, padding: 4, background: 'var(--ps-cloud-gray)', borderRadius: 10, border: '1px solid var(--ps-line)' }}>
          {[['focus', 'cards', 'Focus'], ['split', 'panel', 'Split']].map(([k, ic, lab]) => (
            <button key={k} title={lab + ' layout'} onClick={() => setLayout(k)} style={{
              display: 'inline-flex', alignItems: 'center', gap: 7, fontFamily: 'var(--font-sans)', fontSize: 13, fontWeight: 600,
              cursor: 'pointer', border: 'none', padding: '6px 12px', borderRadius: 7,
              background: layout === k ? 'var(--ps-white)' : 'transparent', color: layout === k ? 'var(--ps-navy)' : 'var(--fg-3)',
              boxShadow: layout === k ? 'var(--sh-1)' : 'none' }}>
              <Icon name={ic} size={15} />{lab}
            </button>
          ))}
        </div>
        <div style={{ width: 110, height: 6, background: 'var(--ps-line)', borderRadius: 6, overflow: 'hidden' }}>
          <div style={{ width: `${(pos / total) * 100}%`, height: '100%', background: 'var(--ps-primary-blue)', transition: 'width .3s' }} />
        </div>
      </div>
    </div>
  );
}

function ImageStage({ rec, layout }) {
  const cap = layout === 'split' ? 'calc(100vh - 200px)' : '60vh';
  return (
    <div style={{ background: 'var(--ps-navy)', borderRadius: 18, overflow: 'hidden',
      boxShadow: 'var(--sh-3)', display: 'flex', alignItems: 'center', justifyContent: 'center', maxHeight: cap }}>
      <img src={rec.dataURL} alt={rec.name} style={{ maxWidth: '100%', maxHeight: cap, objectFit: 'contain', display: 'block' }} />
    </div>
  );
}

window.Review = Review;
