// ===========================================================
// TodayCard — a reason to open the site today, and the streak that rewards it.
//
// Album of the Day has run as an email since July with ZERO in-app surface: the
// only true daily cadence in the product was invisible to anyone who came to the
// site. And every ladder here is keyed to collection size (tiers, nurture cohorts,
// badges), so nothing rewarded a visit — New Spinner to Enthusiast is 40 records,
// a months-long loop, against DAU:MAU of 7%.
//
// The pick MUST match that morning's email or the two contradict each other, so it
// replicates api/collection-digest.js exactly:
//   dayIndex() = floor(UTC-midnight ms / 86400000)
//   index      = (dayIndex * 31) % 100      // gcd(31,100)=1, a full permutation
// window.BBR_ALBUMS is rank-ordered and identical to lib/canon.js (verified), so
// the same index yields the same record. Confirmed against the live email.
//
// The streak comes from store.visit (profiles.streak_days via touch_visit()).
// Guests and pre-migration users have visit == null, and then no streak is shown
// rather than a zero — a "0-day streak" is worse than none.
// ===========================================================
const { useState: useTdState, useEffect: useTdEffect } = React;

function bbrDayIndex() {
  const n = new Date();
  return Math.floor(Date.UTC(n.getUTCFullYear(), n.getUTCMonth(), n.getUTCDate()) / 86400000);
}

// Exported so the album page and any future surface can agree on the same pick.
function bbrAlbumOfDay(offset) {
  const albums = window.BBR_ALBUMS || [];
  if (!albums.length) return null;
  const i = (((bbrDayIndex() + (Number(offset) || 0)) * 31) % albums.length + albums.length) % albums.length;
  return albums[i];
}

function TodayCard({ onAlbum }) {
  const store = window.BBR_store;
  const [, force] = useTdState(0);
  useTdEffect(() => (store ? store.subscribe(() => force((n) => n + 1)) : undefined), []);

  const album = bbrAlbumOfDay(0);
  if (!album) return null;

  const visit = store && store.visit;
  const streak = visit && visit.streakDays > 1 ? visit.streakDays : 0;
  const essay = (window.ESSAYS_FULL && window.ESSAYS_FULL[album.slug]) || {};
  // The list blurb is the hook the email uses too; fall back to the dek.
  // window.BLURBS (data/blurbs.js), keyed by rank — the same hook the list page and
  // the email use. NOT BBR_BLURBS, which does not exist.
  const hook = (window.BLURBS && window.BLURBS[album.rank]) ||
    (essay.essay && essay.essay.dek) || "";

  return (
    <section className="td" aria-labelledby="td-h">
      <div className="td-inner">
        <div className="td-media">
          <img src={"/covers/" + album.slug + ".jpg"} alt={album.title + " — " + album.artist}
               width="128" height="128" loading="lazy" />
        </div>
        <div className="td-body">
          <div className="td-kicker">
            Today from the canon
            {streak ? <span className="td-streak" title="Consecutive days you've visited">
              · {streak}-day streak
            </span> : null}
          </div>
          <h2 className="td-h" id="td-h">
            <span className="td-rank">№{album.rank}</span> {album.title}
          </h2>
          <div className="td-artist">{album.artist} · {album.year}</div>
          {hook ? <p className="td-hook">{hook}</p> : null}
          <button className="td-cta" onClick={() => onAlbum && onAlbum(album.slug)}>
            Read the case for №{album.rank} →
          </button>
          <div className="td-fine">
            A different record every day, the same one as the morning email.
          </div>
        </div>
      </div>
    </section>
  );
}

Object.assign(window, { TodayCard, bbrAlbumOfDay, bbrDayIndex });
