// Vanta review — what the history says. Fetched on demand from /vanta/review.
// Every table labels its sample; a pattern is stated only when the numbers
// support it, and a thin sample says "thin" instead of pretending.

function useReview() {
  const [data, setData] = React.useState(window.VANTA_REVIEW || null);
  React.useEffect(() => {
    let alive = true;
    const load = () => fetch('/vanta/review')
      .then(r => (r.ok ? r.json() : null))
      .then(d => { window.VANTA_REVIEW = d || null; if (alive) setData(d || undefined); })
      .catch(() => { if (alive) setData(undefined); });
    load();
    const on = () => load();
    window.addEventListener('vanta:changed', on);
    return () => { alive = false; window.removeEventListener('vanta:changed', on); };
  }, []);
  return data;
}

function Table({ P, head, rows, cols }) {
  const S = vStyles(P);
  return (
    <div style={{ overflowX: 'auto' }}>
      <div style={{ display: 'grid', gridTemplateColumns: cols, columnGap: 14, rowGap: 0, minWidth: 320, fontSize: 13 }}>
        {head.map((h, i) => <span key={'h' + i} style={{ ...S.caps, color: P.ink4, padding: '0 0 6px', textAlign: i ? 'right' : 'left' }}>{h}</span>)}
        {rows.map((r, ri) => r.map((c, ci) => (
          <span key={ri + ':' + ci} style={{
            padding: '6px 0', borderTop: `1px solid ${P.rule}`, textAlign: ci ? 'right' : 'left',
            color: ci ? P.ink2 : P.ink, ...(ci ? S.num : {}), minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
          }}>{c}</span>
        )))}
      </div>
    </div>
  );
}

function WeekBars({ P, values, goal, color }) {
  const max = Math.max(goal || 0, ...values, 1);
  return (
    <span style={{ display: 'inline-flex', gap: 3, alignItems: 'flex-end', height: 18 }} aria-hidden="true">
      {values.map((v, i) => (
        <span key={i} title={String(v)} style={{ width: 7, height: Math.max(2, Math.round((v / max) * 18)), borderRadius: 2, background: goal && v >= goal ? color : P.ink4, opacity: v ? 1 : 0.35 }} />
      ))}
    </span>
  );
}

function VantaReview({ P }) {
  const S = vStyles(P);
  const d = useReview();
  const pct = v => (v == null ? '—' : `${Math.round(v * 100)}%`);
  const wide = useWide(900);

  if (d === null) return <Empty P={P}>reading the history…</Empty>;
  if (d === undefined) return <Card P={P}><div style={{ fontSize: 13.5, color: P.ink2 }}>The review is unreachable right now, so there is nothing honest to show.</div></Card>;

  const findings = (d.habits || []).filter(h => h.finding);
  const thinCount = (d.habits || []).filter(h => h.thin).length;

  return (
    <div style={{ display: 'grid', gridTemplateColumns: wide ? 'minmax(0, 1fr) minmax(0, 1fr)' : '1fr', gap: 14, alignItems: 'start' }}>
      <div style={{ display: 'grid', gap: 14 }}>
        <Card P={P} title="habits · last 8 weeks" aside={d.rhythm ? <span style={{ ...S.caps, color: P.ink4 }}>{d.rhythm.streak ? `${d.rhythm.streak}-day streak` : 'no streak'}</span> : null}>
          {findings.length > 0 ? (
            <div style={{ marginBottom: 12 }}>
              {findings.map(h => <div key={h.habit} style={{ fontSize: 13.5, color: P.ink, padding: '3px 0' }}><span style={{ ...S.serif, fontSize: 15 }}>{h.label}</span> <span style={{ color: P.ink2 }}>{h.finding}</span></div>)}
            </div>
          ) : (
            <Empty P={P}>{thinCount ? `No weekday-versus-weekend pattern stands out yet (${thinCount} habit${thinCount === 1 ? '' : 's'} still thin on data).` : 'No weekday-versus-weekend pattern stands out.'}</Empty>
          )}
          {d.habits && d.habits.length > 0 && (
            <Table P={P} cols="minmax(0, 1.6fr) 1fr 1fr 0.7fr" head={['habit', 'weekdays', 'weekends', 'days']}
              rows={d.habits.map(h => [h.label, pct(h.weekday.rate), pct(h.weekend.rate), `${h.weekday.n + h.weekend.n}${h.thin ? ' · thin' : ''}`])} />
          )}
        </Card>

        <VRhythm P={P} flush />

        <Card P={P} title="hobbies · days per week">
          {d.hobbies && d.hobbies.rows.length ? (
            <Table P={P} cols="minmax(0, 1.4fr) auto 1fr 0.6fr" head={['practice', 'weeks', 'this wk', 'goal']}
              rows={d.hobbies.rows.map(h => [h.label, <WeekBars key={h.key} P={P} values={h.counts} goal={h.goal} color={P.accent} />, String(h.counts[h.counts.length - 1] ?? 0), String(h.goal)])} />
          ) : <Empty P={P}>no practice logged yet.</Empty>}
          {d.hobbies && d.hobbies.weeks.length > 0 && <div style={{ ...S.caps, color: P.ink4, marginTop: 8 }}>weeks of {vantaDueLabel(d.hobbies.weeks[0])} → {vantaDueLabel(d.hobbies.weeks[d.hobbies.weeks.length - 1])} · a bar reaches the goal when it is full colour</div>}
        </Card>
      </div>

      <div style={{ display: 'grid', gap: 14 }}>
        <Card P={P} title="chores · against cadence">
          {d.chores && d.chores.length ? (
            <Table P={P} cols="minmax(0, 1.4fr) 0.8fr 0.9fr 0.9fr 0.6fr" head={['chore', 'plan', 'actual', 'on time', 'n']}
              rows={d.chores.map(c => [c.label, `${c.cadenceDays}d`, c.avgIntervalDays == null ? '—' : `${c.avgIntervalDays}d`, pct(c.onTimeRate), String(c.n)])} />
          ) : <Empty P={P}>no chores with history yet. Done from the today card; the record starts now.</Empty>}
          <div style={{ ...S.caps, color: P.ink4, marginTop: 8 }}>actual = average days between completions · on time = within plan plus a day</div>
        </Card>

        <Card P={P} title="reading">
          {d.reading ? (
            <React.Fragment>
              <div style={{ display: 'flex', gap: 18, flexWrap: 'wrap', marginBottom: 10 }}>
                {[
                  ['pages / reading day', d.reading.avgPagesPerReadingDay == null ? '—' : String(d.reading.avgPagesPerReadingDay), 'last 28 days'],
                  ['reading days', String(d.reading.readingDays), 'last 28 days'],
                  ['books finished', String(d.reading.booksFinished), 'all time'],
                  ['days to finish', d.reading.daysToFinish == null ? '—' : String(d.reading.daysToFinish), 'at that pace'],
                ].map(([k, v, s]) => (
                  <div key={k}>
                    <div style={{ ...S.caps, color: P.ink4 }}>{k}</div>
                    <div style={{ ...S.num, fontSize: 20, color: P.ink }}>{v}</div>
                    <div style={{ fontSize: 11, color: P.ink4 }}>{s}</div>
                  </div>
                ))}
              </div>
              {d.reading.pagesPerWeek.length > 0 && (
                <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 10 }}>
                  <WeekBars P={P} values={d.reading.pagesPerWeek.map(w => w.pages)} color={P.accent} />
                  <span style={{ ...S.caps, color: P.ink4 }}>pages per week · {d.reading.pagesPerWeek.length} week{d.reading.pagesPerWeek.length === 1 ? '' : 's'}</span>
                </div>
              )}
              {d.reading.books.length ? (
                <Table P={P} cols="minmax(0, 2fr) 1fr 0.8fr" head={['book', 'page', 'status']}
                  rows={d.reading.books.map(b => [b.title + (b.author ? ` · ${b.author}` : ''), b.totalPages ? `${b.currentPage} / ${b.totalPages}` : String(b.currentPage), b.status])} />
              ) : <Empty P={P}>no books yet.</Empty>}
            </React.Fragment>
          ) : <Empty P={P}>reading history unreachable.</Empty>}
        </Card>

        <Card P={P} title="pm track · weekly" aside={d.hit && d.hit.n ? <span style={{ ...S.caps, color: P.ink4 }}>hit rate 30d {Math.round(d.hit.rate * 100)}% · {d.hit.hits}/{d.hit.n}{d.hit.thin ? ' · small sample' : ''}</span> : null}>
          {d.pm && d.pm.length ? (
            <Table P={P} cols="minmax(0, 1.2fr) 1fr 1fr 1fr" head={['week of', 'study', 'applications', 'calls hit']}
              rows={d.pm.map(w => [vantaDueLabel(w.week), w.hours ? `${w.hours}h` : '—', w.applications ? String(w.applications) : '—', w.n ? `${w.hits}/${w.n}` : '—'])} />
          ) : <Empty P={P}>no weeks on record yet — /study, /apply and a reply to the morning brief start it.</Empty>}
        </Card>
      </div>
    </div>
  );
}

Object.assign(window, { VantaReview });
