/* Medina Fight Lab — Athlete screens. Server-backed; includes round timer + per-round logging. */
const { Badge, Stat, Button, Input, Avatar, Switch, Card } = window.MedinaFightLabDesignSystem_ed6365;

/* ---------- Daily Message Bell ---------- */
const DAILY_MSGS = [
  "The work you put in today is the foundation someone else can only dream about.",
  "Pain is the price of admission. Champions pay it willingly.",
  "Your body remembers every rep. Train like it matters — because it does.",
  "The fight doesn't start in the ring. It starts when the alarm goes off.",
  "Discipline is just love for your future self.",
  "Iron sharpens iron. Show up and be the whetstone.",
  "Every session is a deposit. Every skip is a withdrawal. Know your balance.",
  "You don't rise to the occasion — you fall to your preparation.",
  "Fatigue is temporary. The version of yourself you're building is permanent.",
  "The best fighters in the world still do the basics. Do the basics.",
  "Healing is not weakness. Recovery is part of the work.",
  "No one sees your 5am. Your competition does.",
  "Strength isn't built in comfort. Neither is character.",
  "One more rep when it burns is where champions are forged.",
  "The body achieves what the mind believes. Train both.",
  "You're not just building a fighter — you're building a person.",
  "Progress is quiet. Keep going anyway.",
  "Today's sore muscles are tomorrow's armour.",
  "Trust the process even when the results aren't there yet.",
  "Show up with intention. The rest follows.",
  "A warrior prepares. A champion recovers. Be both.",
  "The gym floor doesn't care about your mood. Neither does your opponent.",
  "Every setback is just a different angle of attack.",
  "Hard days build the mental toughness soft days can't.",
  "Your weaknesses are just strengths you haven't built yet.",
  "Fight camps end. The habits you build last forever.",
  "The work is the reward. Everything else is a bonus.",
  "You can't pour from an empty cup — rest is not optional.",
  "Some days the win is just showing up. That counts.",
  "The athlete who recovers fastest wins. Prioritise it.",
  "Precision beats power. Consistency beats intensity.",
  "You were built for this. Act like it.",
  "Pressure either breaks pipes or makes diamonds. Your choice.",
  "Progress compounds. The reps you do today pay interest.",
  "Every fighter has a style. The great ones know exactly why.",
  "Not every day feels like a breakthrough. Not every breakthrough feels like one.",
  "Grit is the gap between motivation and discipline. Fill it.",
  "Your opponent is also tired. Who trained harder?",
  "Science doesn't care about excuses. Neither should your program.",
  "Injury is information, not a full stop.",
  "The body is the weapon. Sharpen it daily.",
  "You don't need to be fearless. You need to move despite the fear.",
  "The mat doesn't lie. Neither does the barbell.",
  "Every rep is a vote for the athlete you're becoming.",
  "Small consistent wins beat sporadic heroics every time.",
  "Your ceiling is higher than you think. Prove it today.",
  "Rest is not retreat. It's strategy.",
  "The fight is 3 minutes. The prep is 3 months. Respect both.",
  "Mental toughness is a skill. It's trained, not born.",
  "What you do when no one is watching determines everything.",
  "The best version of you is already in there. Chase it.",
  "Control what you can. Attack what you can't.",
  "Champions are made in the moments you want to quit and don't.",
  "Mobility today is durability tomorrow.",
  "Every elite athlete you admire was once exactly where you are.",
  "Hard training easy fight. Easy training hard fight.",
  "You are the sum of your habits. Build good ones, ruthlessly.",
  "The body adapts to what you consistently demand of it. Demand more.",
  "Breathe. Reset. Go again.",
  "Your comeback starts the same way your first win did — one session at a time.",
  "Don't just train to compete. Train to last.",
  "Reps don't lie. Hours don't lie. The scoreboard doesn't lie.",
  "Every scar is a story. Every story is a lesson. Keep earning them.",
  "Champions don't wait for perfect conditions. They create them.",
];

function getDailyMsg() {
  const d = new Date();
  const start = new Date(d.getFullYear(), 0, 0);
  const day = Math.floor((d - start) / 86400000);
  return DAILY_MSGS[day % DAILY_MSGS.length];
}
function getDailyKey() {
  const d = new Date();
  return "mfl_app_msg_" + d.getFullYear() + "_" + Math.floor((d - new Date(d.getFullYear(), 0, 0)) / 86400000);
}

function DailyBell() {
  const { MFLIcons } = window;
  const [unread, setUnread] = React.useState(() => !localStorage.getItem(getDailyKey()));
  const [open, setOpen] = React.useState(false);

  const handleClick = () => {
    setUnread(false);
    localStorage.setItem(getDailyKey(), "1");
    setOpen(true);
    setTimeout(() => setOpen(false), 7000);
  };

  return (
    <React.Fragment>
      <button className="mfl-bell" onClick={handleClick} aria-label="Daily message">
        {MFLIcons.bell({ width: 19, height: 19 })}
        {unread && <span className="mfl-bell__dot" />}
      </button>
      {open && (
        <div className="mfl-msg-toast">
          <div className="mfl-msg-toast__label">Daily Message</div>
          <div className="mfl-msg-toast__text">{getDailyMsg()}</div>
          <button className="mfl-msg-toast__close" onClick={() => setOpen(false)}>×</button>
        </div>
      )}
    </React.Fragment>
  );
}

function parseMin(t) {
  if (!t) return 0;
  var m = String(t).match(/(\d+)\s*[×x]\s*(\d+)/);
  if (m) return (+m[1]) * (+m[2]);
  var s = String(t).match(/(\d+)/);
  return s ? +s[1] : 0;
}
function parseInterval(t) {
  // returns { rounds, workSec, restSec }
  var m = String(t || "").match(/(\d+)\s*[×x]\s*(\d+)/);
  if (m) return { rounds: +m[1], workSec: (+m[2]) * 60, restSec: 60 };
  var s = String(t || "").match(/(\d+)/);
  return { rounds: 1, workSec: (s ? +s[1] : 3) * 60, restSec: 0 };
}
function mmss(sec) {
  sec = Math.max(0, Math.round(sec));
  var m = Math.floor(sec / 60), s = sec % 60;
  return m + ":" + String(s).padStart(2, "0");
}
function beep(freq) {
  try {
    var Ctx = window.AudioContext || window.webkitAudioContext; if (!Ctx) return;
    var ac = beep._ac || (beep._ac = new Ctx());
    var o = ac.createOscillator(), g = ac.createGain();
    o.connect(g); g.connect(ac.destination);
    o.frequency.value = freq || 880; o.type = "sine";
    g.gain.setValueAtTime(0.001, ac.currentTime);
    g.gain.exponentialRampToValueAtTime(0.3, ac.currentTime + 0.02);
    g.gain.exponentialRampToValueAtTime(0.001, ac.currentTime + 0.35);
    o.start(); o.stop(ac.currentTime + 0.36);
  } catch (e) {}
}

/* ---------- shared bits ---------- */
function RoundItem({ r, isDone, onToggle }) {
  const { MFLIcons } = window;
  return (
    <div className={"aa-round" + (isDone ? " aa-round--done" : "")}>
      <span className={"aa-check" + (isDone ? " aa-check--on" : "")} onClick={onToggle}>
        {isDone ? MFLIcons.check({ width: 16, height: 16 }) : null}
      </span>
      <div className="aa-round__main">
        <div className="aa-round__label">{r.label}</div>
        <div className="aa-round__detail">{r.detail}</div>
      </div>
      <span className="aa-round__time">{r.time}</span>
    </div>
  );
}

function AppBar({ title, right }) {
  return (
    <header className="aa-bar">
      <img src="icons/icon-192.png" alt="Medina Fight Lab" />
      <span className="aa-bar__t">{title}</span>
      <span className="aa-bar__icon">{right || <DailyBell />}</span>
    </header>
  );
}

function TabBar({ tab, setTab }) {
  const { MFLIcons } = window;
  const tabs = [
    { id: "today", label: "Today", icon: MFLIcons.zap },
    { id: "schedule", label: "Schedule", icon: MFLIcons.calendar },
    { id: "messages", label: "Coach", icon: MFLIcons.message },
    { id: "history", label: "History", icon: MFLIcons.clock },
    { id: "profile", label: "Profile", icon: MFLIcons.user },
  ];
  return (
    <nav className="aa-tabbar">
      {tabs.map((t) => (
        <button key={t.id} className={"aa-tab" + (tab === t.id ? " aa-tab--active" : "")} onClick={() => setTab(t.id)}>
          {t.icon({ width: 22, height: 22 })}<span>{t.label}</span>
        </button>
      ))}
    </nav>
  );
}

/* ---------- Round timer (work / rest intervals) ---------- */
function RoundTimer({ round }) {
  const { MFLIcons } = window;
  const plan = React.useMemo(() => parseInterval(round.time), [round.time]);
  // build phase queue
  const phases = React.useMemo(() => {
    const q = [];
    for (let i = 0; i < plan.rounds; i++) {
      q.push({ kind: "WORK", sec: plan.workSec, n: i + 1 });
      if (plan.restSec && i < plan.rounds - 1) q.push({ kind: "REST", sec: plan.restSec, n: i + 1 });
    }
    return q;
  }, [plan]);

  const [idx, setIdx] = React.useState(0);
  const [remaining, setRemaining] = React.useState(phases[0] ? phases[0].sec : 0);
  const [running, setRunning] = React.useState(false);
  const [done, setDone] = React.useState(false);

  React.useEffect(() => { setIdx(0); setRemaining(phases[0] ? phases[0].sec : 0); setRunning(false); setDone(false); }, [phases]);

  React.useEffect(() => {
    if (!running) return;
    const t = setInterval(() => {
      setRemaining((r) => {
        if (r > 1) return r - 1;
        // phase end
        setIdx((curIdx) => {
          const next = curIdx + 1;
          if (next >= phases.length) { setRunning(false); setDone(true); beep(660); return curIdx; }
          beep(phases[next].kind === "WORK" ? 880 : 440);
          setRemaining(phases[next].sec);
          return next;
        });
        return 0;
      });
    }, 1000);
    return () => clearInterval(t);
  }, [running, phases]);

  const cur = phases[idx] || { kind: "WORK", sec: 0, n: 1 };
  const reset = () => { setIdx(0); setRemaining(phases[0] ? phases[0].sec : 0); setRunning(false); setDone(false); };
  const skip = () => {
    const next = idx + 1;
    if (next >= phases.length) { setRunning(false); setDone(true); return; }
    setIdx(next); setRemaining(phases[next].sec);
  };

  return (
    <div className={"aa-timer aa-timer--" + (done ? "done" : cur.kind.toLowerCase())}>
      <div className="aa-timer__phase">
        {done ? "Done" : cur.kind}
        {plan.rounds > 1 && !done ? <span className="aa-timer__rd"> · Rd {cur.n}/{plan.rounds}</span> : null}
      </div>
      <div className="aa-timer__clock">{mmss(remaining)}</div>
      <div className="aa-timer__ctrls">
        <button className="aa-tbtn" onClick={reset} aria-label="Reset">{MFLIcons.arrowLeft({ width: 18, height: 18 })}</button>
        <button className="aa-tbtn aa-tbtn--go" onClick={() => setRunning((x) => !x)} disabled={done}>
          {running ? "Pause" : remaining === (phases[0] ? phases[0].sec : 0) && idx === 0 ? "Start" : "Resume"}
        </button>
        <button className="aa-tbtn" onClick={skip} aria-label="Skip" disabled={done}>{MFLIcons.chevronR({ width: 18, height: 18 })}</button>
      </div>
    </div>
  );
}

/* ---------- per-round log ---------- */
function RoundLog({ log, onChange }) {
  const { MFLIcons } = window;
  const L = log || {};
  // sets array is the source of truth; migrate any old flat {weight,reps,rpe} into one set
  const sets = Array.isArray(L.sets) ? L.sets
    : (L.weight || L.reps || L.rpe) ? [{ weight: L.weight, reps: L.reps, rpe: L.rpe }] : [];
  const [w, setW] = React.useState("");
  const [reps, setReps] = React.useState("");
  const [rpe, setRpe] = React.useState("");

  const logSet = () => {
    if (!String(w).trim() && !String(reps).trim() && !String(rpe).trim()) return;
    const next = sets.concat([{ weight: w, reps: reps, rpe: rpe }]);
    onChange(Object.assign({}, L, { sets: next, weight: undefined, reps: undefined, rpe: undefined }));
    setReps(""); setRpe("");           // carry weight over for the next set, clear reps/rpe
  };
  const removeSet = (i) => onChange(Object.assign({}, L, { sets: sets.filter((_, j) => j !== i) }));
  const numIn = (val, set, ph) => (
    <input className="aa-log__in" inputMode="decimal" value={val} placeholder={ph} onChange={(e) => set(e.target.value)} />
  );

  return (
    <div className="aa-log">
      {sets.length ? (
        <div className="aa-sets">
          <div className="aa-sets__row aa-sets__head"><span>Set</span><span>Weight</span><span>Reps</span><span>RPE</span><span /></div>
          {sets.map((s, i) => (
            <div key={i} className="aa-sets__row">
              <span className="aa-sets__n">{i + 1}</span>
              <span>{s.weight || "—"}</span>
              <span>{s.reps || "—"}</span>
              <span>{s.rpe || "—"}</span>
              <button className="aa-sets__x" onClick={() => removeSet(i)} aria-label="Remove set">×</button>
            </div>
          ))}
        </div>
      ) : null}
      <div className="aa-log__row">
        <label>Weight {numIn(w, setW, "kg")}</label>
        <label>Reps {numIn(reps, setReps, "—")}</label>
        <label>RPE {numIn(rpe, setRpe, "1-10")}</label>
      </div>
      <button className="aa-addset" onClick={logSet}>
        {MFLIcons.plus({ width: 16, height: 16 })} Log set{sets.length ? " · next is set " + (sets.length + 1) : ""}
      </button>
      <input className="aa-log__notes" value={L.notes || ""} placeholder="Notes (how it felt, cues…)"
        onChange={(e) => onChange(Object.assign({}, L, { notes: e.target.value }))} />
    </div>
  );
}

/* ---------- Today ---------- */
function TodayScreen({ session, stats, done, streak, onToggle, onStart, dateLabel, offline }) {
  const { MFLIcons } = window;
  const nextIdx = session.rounds.findIndex((r) => !done.has(r.id));
  const cta = stats.total === 0 ? "No rounds yet" : nextIdx === -1 ? "Session done ✓" : stats.done === 0 ? "Start session" : "Resume";
  return (
    <React.Fragment>
      <AppBar title="Today" right={offline ? <span className="aa-offline">{MFLIcons.moon({ width: 16, height: 16 })}</span> : null} />
      <div className="aa-body">
        <div className="aa-greet">
          <div className="eye">{dateLabel}{offline ? " · offline" : ""}</div>
          <h1>Your session</h1>
        </div>
        <div className="aa-hero">
          <div className="aa-hero__plan">{session.title}</div>
          {session.coachNote ? (
            <div className="aa-hero__note"><span className="bar"></span><p>"{session.coachNote}"</p></div>
          ) : null}
          <div className="aa-hero__meta">
            <Stat size="sm" value={stats.total} label="rounds" onInk />
            <Stat size="sm" value={stats.done} label="complete" onInk />
            <Stat size="sm" value={stats.pct} unit="%" label="done" onInk />
          </div>
        </div>
        <div>
          <div className="aa-section-h">
            <span className="lab">The plan</span>
            <span className="cnt">{stats.done}/{stats.total} complete</span>
          </div>
          <div className="aa-rounds" style={{ marginTop: 10 }}>
            {session.rounds.length === 0
              ? <div className="aa-empty">No rounds in today's session yet.</div>
              : session.rounds.map((r) => (
                  <RoundItem key={r.id} r={r} isDone={done.has(r.id)} onToggle={() => onToggle(r.id)} />
                ))}
          </div>
        </div>
      </div>
      <div className="aa-dock">
        <div className="aa-progress"><div className="aa-progress__fill" style={{ width: stats.pct + "%" }}></div></div>
        <div className="aa-dock__row">
          <span className="aa-dock__meta">{MFLIcons.flame({ width: 15, height: 15 })} {streak}-day streak</span>
          <Button variant="stamp" leftIcon={MFLIcons.zap({ width: 17, height: 17 })} onClick={onStart} disabled={stats.total === 0 || nextIdx === -1}>
            {cta}
          </Button>
        </div>
      </div>
    </React.Fragment>
  );
}

/* ---------- Rest day ---------- */
function RestDayScreen({ streak }) {
  const { MFLIcons } = window;
  return (
    <React.Fragment>
      <AppBar title="Today" />
      <div className="aa-rest">
        <span className="aa-rest__badge">{MFLIcons.moon({ width: 32, height: 32 })}</span>
        <div className="aa-rest__h">Rest day</div>
        <p className="aa-rest__p">No session assigned today. Your coach hasn't set one — recover, hydrate, move easy.</p>
        <Badge variant="completed" dot>{streak}-day streak safe</Badge>
      </div>
    </React.Fragment>
  );
}

/* ---------- Session (focused, with timer + logging) ---------- */
function SessionScreen({ rounds, idx, log, onLog, onComplete, onBack }) {
  const { MFLIcons } = window;
  const r = rounds[idx];
  const move = r.detail ? r.detail.split(",")[0] : r.label;
  return (
    <div className="aa-focus">
      <div className="aa-focus__top">
        <span className="aa-focus__back" onClick={onBack}>{MFLIcons.arrowLeft({ width: 18, height: 18 })}</span>
        <span className="aa-focus__step">{r.label} · {idx + 1}/{rounds.length}</span>
        <div className="aa-dots">
          {rounds.map((x, i) => (
            <span key={x.id} className={"aa-dot" + (i < idx ? " aa-dot--done" : i === idx ? " aa-dot--active" : "")}></span>
          ))}
        </div>
      </div>
      <div className="aa-focus__scroll">
        <div className="aa-focus__card">
          <div className="aa-focus__kind">{r.label}</div>
          <div className="aa-focus__round">{move}</div>
          {r.detail && r.detail.includes(",") ? <div className="aa-focus__detail">{r.detail}</div> : null}
        </div>
        <RoundTimer round={r} />
        <RoundLog key={r.id} log={log} onChange={onLog} />
      </div>
      <Button variant="stamp" size="lg" fullWidth leftIcon={MFLIcons.check({ width: 19, height: 19 })} onClick={onComplete}>
        {idx + 1 >= rounds.length ? "Finish session" : "Mark complete"}
      </Button>
    </div>
  );
}

/* ---------- Week (athlete schedule) ---------- */
const WD_A = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
const MO_A = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
function isoA(d) { return new Date(d.getTime() - d.getTimezoneOffset() * 60000).toISOString().slice(0, 10); }
function mondayA(iso) { const x = new Date(iso + "T00:00:00"); const day = (x.getDay() + 6) % 7; x.setDate(x.getDate() - day); return isoA(x); }
function addDaysA(iso, n) { const d = new Date(iso + "T00:00:00"); d.setDate(d.getDate() + n); return isoA(d); }
const MO_LONG_A = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];

/* ---------- Schedule (calendar; tap a day to see its workouts) ---------- */
function ScheduleScreen({ token }) {
  const { MFLIcons } = window;
  const todayISO = isoA(new Date());
  const [cursor, setCursor] = React.useState(todayISO.slice(0, 7) + "-01"); // first of visible month
  const [selected, setSelected] = React.useState(todayISO);
  const [data, setData] = React.useState(null);
  const [busy, setBusy] = React.useState(true);

  const y = +cursor.slice(0, 4), m = +cursor.slice(5, 7) - 1;
  const firstOfMonth = cursor;
  const lastOfMonth = isoA(new Date(y, m + 1, 0));
  const gridStart = mondayA(firstOfMonth);
  const gridEnd = addDaysA(mondayA(lastOfMonth), 6);
  const cells = React.useMemo(() => {
    const out = []; let d = gridStart;
    while (d <= gridEnd) { out.push(d); d = addDaysA(d, 1); }
    return out;
  }, [gridStart, gridEnd]);

  const load = React.useCallback(async () => {
    setBusy(true);
    try { setData(await window.MFLApi.athleteRange(token, gridStart, gridEnd)); }
    catch (e) { setData({ error: e.message }); }
    setBusy(false);
  }, [token, gridStart, gridEnd]);
  React.useEffect(() => { load(); }, [load]);

  const byDate = {};
  if (data && data.schedule) data.schedule.forEach((s) => { byDate[s.date] = s; });

  const shiftMonth = (n) => {
    const nd = new Date(y, m + n, 1);
    setCursor(isoA(nd).slice(0, 7) + "-01");
  };

  const sel = byDate[selected];
  const selD = new Date(selected + "T00:00:00");
  const selLabel = WD_A[(selD.getDay() + 6) % 7] + " · " + MO_LONG_A[selD.getMonth()] + " " + selD.getDate();

  return (
    <React.Fragment>
      <AppBar title="Schedule" />
      <div className="aa-page">
        <div className="aa-greet">
          <div className="eye">Your schedule</div>
          <h1>What's coming</h1>
        </div>

        <div className="aa-cal">
          <div className="aa-cal__nav">
            <button onClick={() => shiftMonth(-1)} aria-label="Previous month">{MFLIcons.arrowLeft({ width: 16, height: 16 })}</button>
            <span className="aa-cal__month">{MO_LONG_A[m]} {y}</span>
            <button onClick={() => shiftMonth(1)} aria-label="Next month">{MFLIcons.chevronR({ width: 16, height: 16 })}</button>
          </div>
          <div className="aa-cal__wdrow">
            {WD_A.map((w) => <span key={w} className="aa-cal__wd">{w[0]}</span>)}
          </div>
          <div className="aa-cal__grid">
            {cells.map((iso) => {
              const d = new Date(iso + "T00:00:00");
              const inMonth = d.getMonth() === m;
              const entry = byDate[iso];
              const hasSession = entry && entry.session;
              const fin = entry && entry.progress && entry.progress.finished;
              const cls = "aa-cal__cell"
                + (inMonth ? "" : " aa-cal__cell--out")
                + (iso === todayISO ? " aa-cal__cell--today" : "")
                + (iso === selected ? " aa-cal__cell--sel" : "")
                + (hasSession ? " aa-cal__cell--has" : "")
                + (fin ? " aa-cal__cell--done" : "");
              return (
                <button key={iso} className={cls} onClick={() => setSelected(iso)}>
                  <span className="n">{d.getDate()}</span>
                  {hasSession ? <span className="dot">{fin ? MFLIcons.check({ width: 9, height: 9 }) : null}</span> : null}
                </button>
              );
            })}
          </div>
        </div>

        <div className="aa-section-h" style={{ marginTop: 4 }}>
          <span className="lab">{selLabel}{selected === todayISO ? " · today" : ""}</span>
          {sel && sel.session ? <span className="cnt">{sel.session.rounds.length} drills</span> : null}
        </div>

        {busy && !data ? <div className="aa-empty">Loading…</div>
          : !sel || !sel.session ? <div className="aa-empty">No workout this day — rest &amp; recover.</div>
          : (
            <div className="aa-caldetail">
              <div className="aa-caldetail__title">
                {sel.session.title}
                {sel.progress ? <span className={"aa-caldetail__pct" + (sel.progress.finished ? " is-done" : "")}>{sel.progress.pct}%</span> : null}
              </div>
              {sel.session.focus ? <div className="aa-caldetail__focus">{sel.session.focus}</div> : null}
              {sel.session.coachNote ? <div className="aa-wday__note">"{sel.session.coachNote}"</div> : null}
              <div className="aa-week" style={{ marginTop: 10 }}>
                {sel.session.rounds.map((r) => (
                  <div key={r.id} className="aa-wround">
                    <div className="aa-wround__main">
                      <div className="aa-wround__label">{r.label}</div>
                      <div className="aa-wround__detail">{r.detail}</div>
                    </div>
                    {r.time && r.time !== "—" ? <span className="aa-wround__time">{r.time}</span> : null}
                  </div>
                ))}
              </div>
            </div>
          )}
      </div>
    </React.Fragment>
  );
}

function WeekScreen({ token }) {
  const { MFLIcons } = window;
  const todayISO = isoA(new Date());
  const [weekStart, setWeekStart] = React.useState(mondayA(todayISO));
  const [data, setData] = React.useState(null);
  const [busy, setBusy] = React.useState(true);
  const [open, setOpen] = React.useState({});

  const load = React.useCallback(async () => {
    setBusy(true);
    try { setData(await window.MFLApi.athleteWeek(token, weekStart)); }
    catch (e) { setData({ error: e.message }); }
    setBusy(false);
  }, [token, weekStart]);
  React.useEffect(() => { load(); }, [load]);

  const shift = (n) => { setWeekStart(addDaysA(weekStart, n * 7)); setOpen({}); };
  const toggle = (d) => setOpen((o) => Object.assign({}, o, { [d]: !o[d] }));

  const weekEnd = addDaysA(weekStart, 6);
  const range = MO_A[new Date(weekStart + "T00:00:00").getMonth()] + " " + new Date(weekStart + "T00:00:00").getDate()
    + " – " + MO_A[new Date(weekEnd + "T00:00:00").getMonth()] + " " + new Date(weekEnd + "T00:00:00").getDate();

  const schedule = (data && data.schedule) || [];
  const trainingDays = schedule.filter((s) => s.session).length;

  return (
    <React.Fragment>
      <AppBar title="Week" />
      <div className="aa-page">
        <div className="aa-greet">
          <div className="eye">Your schedule</div>
          <h1>The week ahead</h1>
        </div>

        <div className="aa-weeknav">
          <button onClick={() => shift(-1)} aria-label="Previous week">{MFLIcons.arrowLeft({ width: 16, height: 16 })}</button>
          <span className="aa-weeknav__range">{range}</span>
          <button onClick={() => shift(1)} aria-label="Next week">{MFLIcons.chevronR({ width: 16, height: 16 })}</button>
        </div>

        {busy && !data ? <div className="aa-empty">Loading your week…</div>
          : data && data.error ? <div className="aa-empty">{data.error}</div>
          : (
            <React.Fragment>
              <div className="aa-section-h"><span className="lab">7 days</span><span className="cnt">{trainingDays} training · {7 - trainingDays} rest</span></div>
              <div className="aa-week">
                {schedule.map((s) => {
                  const d = new Date(s.date + "T00:00:00");
                  const isToday = s.date === data.today;
                  const sess = s.session;
                  const isOpen = !!open[s.date];
                  const pct = s.progress ? s.progress.pct : null;
                  return (
                    <div key={s.date} className={"aa-wday" + (isToday ? " aa-wday--today" : "") + (sess ? "" : " aa-wday--rest")}>
                      <button className="aa-wday__head" onClick={() => sess && toggle(s.date)} aria-expanded={isOpen}>
                        <div className="aa-wday__date">
                          <span className="wd">{WD_A[(d.getDay() + 6) % 7]}</span>
                          <span className="dn">{d.getDate()}</span>
                        </div>
                        <div className="aa-wday__main">
                          {sess ? (
                            <React.Fragment>
                              <div className="aa-wday__title">{sess.title}</div>
                              <div className="aa-wday__meta">{sess.focus ? sess.focus + " · " : ""}{sess.rounds.length} drill{sess.rounds.length === 1 ? "" : "s"}</div>
                            </React.Fragment>
                          ) : (
                            <React.Fragment>
                              <div className="aa-wday__title aa-wday__title--rest">Rest day</div>
                              <div className="aa-wday__meta">Recover, hydrate, move easy</div>
                            </React.Fragment>
                          )}
                        </div>
                        <div className="aa-wday__right">
                          {isToday ? <Badge variant="assigned" dot>Today</Badge> : null}
                          {pct != null ? <Badge variant={s.progress.finished ? "completed" : "progress"} dot>{pct}%</Badge> : null}
                          {sess ? <span className={"aa-wday__chev" + (isOpen ? " aa-wday__chev--open" : "")}>{MFLIcons.chevronR({ width: 16, height: 16 })}</span> : null}
                        </div>
                      </button>
                      {sess && isOpen ? (
                        <div className="aa-wday__rounds">
                          {sess.coachNote ? <div className="aa-wday__note">"{sess.coachNote}"</div> : null}
                          {sess.rounds.length === 0 ? <div className="aa-empty">No drills yet.</div>
                            : sess.rounds.map((r) => (
                                <div key={r.id} className="aa-wround">
                                  <div className="aa-wround__main">
                                    <div className="aa-wround__label">{r.label}</div>
                                    <div className="aa-wround__detail">{r.detail}</div>
                                  </div>
                                  {r.time && r.time !== "—" ? <span className="aa-wround__time">{r.time}</span> : null}
                                </div>
                              ))}
                        </div>
                      ) : null}
                    </div>
                  );
                })}
              </div>
            </React.Fragment>
          )}
      </div>
    </React.Fragment>
  );
}

/* ---------- Messages (athlete → coach) ---------- */
function msgTime(iso) {
  const d = new Date(iso); const now = new Date();
  const sameDay = d.toDateString() === now.toDateString();
  const t = d.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" });
  return sameDay ? t : (MO_A[d.getMonth()] + " " + d.getDate() + " · " + t);
}
function MessagesScreen({ token, coachName }) {
  const { MFLIcons } = window;
  const [msgs, setMsgs] = React.useState(null);
  const [text, setText] = React.useState("");
  const [sending, setSending] = React.useState(false);
  const endRef = React.useRef(null);

  const load = React.useCallback(async () => {
    try { const d = await window.MFLApi.athleteMessages(token); setMsgs(d.messages || []); }
    catch (e) { setMsgs([]); }
  }, [token]);
  React.useEffect(() => { load(); }, [load]);
  React.useEffect(() => { if (endRef.current) endRef.current.scrollIntoView(); }, [msgs]);

  const send = async () => {
    const t = text.trim(); if (!t || sending) return;
    setSending(true);
    const optimistic = { id: "tmp" + Date.now(), sender: "athlete", body: t, created_at: new Date().toISOString() };
    setMsgs((m) => (m || []).concat([optimistic])); setText("");
    try { await window.MFLApi.athleteSendMessage(token, t); await load(); }
    catch (e) { /* keep optimistic; will reconcile on next load */ }
    setSending(false);
  };
  const onKey = (e) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); send(); } };

  return (
    <React.Fragment>
      <AppBar title="Coach" right={MFLIcons.message({ width: 19, height: 19 })} />
      <div className="aa-chat">
        <div className="aa-chat__intro">
          <div className="eye">Direct line</div>
          <h1>Message {coachName ? coachName.split(" ").slice(-1)[0] : "Coach"}</h1>
          <p>Questions or concerns about your training? Send them here — your coach gets them.</p>
        </div>
        <div className="aa-chat__scroll">
          {msgs == null ? <div className="aa-empty">Loading…</div>
            : msgs.length === 0 ? <div className="aa-empty">No messages yet. Say hi or ask anything.</div>
            : msgs.map((m) => (
                <div key={m.id} className={"aa-bubble aa-bubble--" + (m.sender === "athlete" ? "me" : "coach")}>
                  <div className="aa-bubble__body">{m.body}</div>
                  <div className="aa-bubble__time">{msgTime(m.created_at)}</div>
                </div>
              ))}
          <div ref={endRef} />
        </div>
      </div>
      <div className="aa-chat__dock">
        <textarea className="aa-chat__in" rows={1} value={text} placeholder="Type a message…"
          onChange={(e) => setText(e.target.value)} onKeyDown={onKey} />
        <button className="aa-chat__send" onClick={send} disabled={!text.trim() || sending} aria-label="Send">
          {MFLIcons.send({ width: 20, height: 20 })}
        </button>
      </div>
    </React.Fragment>
  );
}

/* ---------- History ---------- */
function HistoryScreen({ history, week, MONTHS }) {
  const ringColor = (pct) => pct >= 100 ? "var(--green-500)" : pct >= 80 ? "var(--amber-500)" : "var(--scarlet-500)";
  const ord = (n) => { const s = ["th", "st", "nd", "rd"], v = n % 100; return n + (s[(v - 20) % 10] || s[v] || s[0]); };
  const fmtMD = (iso) => { const d = new Date(iso + "T00:00:00"); return MO_LONG_A[d.getMonth()] + " " + ord(d.getDate()); };
  // group completed sessions into calendar weeks (Mon–Sun), newest first
  const groups = [];
  const idx = {};
  history.slice().sort((a, b) => (a.iso < b.iso ? 1 : a.iso > b.iso ? -1 : 0)).forEach((h) => {
    const wk = mondayA(h.iso);
    if (idx[wk] == null) { idx[wk] = groups.length; groups.push({ wk, items: [] }); }
    groups[idx[wk]].items.push(h);
  });
  groups.forEach((g) => { g.end = addDaysA(g.wk, 6); g.adh = Math.round(g.items.reduce((a, h) => a + h.pct, 0) / g.items.length); });

  // collapsible week tabs — most recent week open by default
  const [open, setOpen] = React.useState(() => (groups[0] ? { [groups[0].wk]: true } : {}));
  const toggle = (wk) => setOpen((o) => Object.assign({}, o, { [wk]: !o[wk] }));

  return (
    <React.Fragment>
      <AppBar title="History" />
      <div className="aa-page">
        <h2 className="aa-h2">This week</h2>
        <div className="aa-summary">
          <Card><Stat size="sm" value={week.sessions} label="Sessions" /></Card>
          <Card><Stat size="sm" value={week.rounds} label="Rounds" /></Card>
          <Card><Stat size="sm" value={week.adherence} unit="%" label="Adherence" /></Card>
        </div>
        <div className="aa-section-h"><span className="lab">By week</span><span className="cnt">{groups.length} week{groups.length === 1 ? "" : "s"}</span></div>
        {history.length === 0 ? (
          <div className="aa-empty">No sessions logged yet. Finish today's work and it lands here.</div>
        ) : (
          <div className="aa-histweeks">
            {groups.map((g) => {
              const isOpen = !!open[g.wk];
              return (
                <div key={g.wk} className={"aa-histweek" + (isOpen ? " aa-histweek--open" : "")}>
                  <button className="aa-histweek__tab" onClick={() => toggle(g.wk)} aria-expanded={isOpen}>
                    <span className={"aa-histweek__chev" + (isOpen ? " is-open" : "")}>{window.MFLIcons.chevronR({ width: 16, height: 16 })}</span>
                    <span className="aa-histweek__rng">{fmtMD(g.wk)} – {fmtMD(g.end)}</span>
                    <span className="aa-histweek__cnt">{g.items.length} · {g.adh}%</span>
                  </button>
                  {isOpen ? (
                    <div className="aa-hist">
                      {g.items.map((h) => {
                        const d = new Date(h.iso + "T00:00:00");
                        const day = String(d.getDate()).padStart(2, "0");
                        const mon = MONTHS[d.getMonth()];
                        return (
                          <div key={h.id} className="aa-histrow">
                            <div className="aa-histrow__date"><div className="d">{day}</div><div className="m">{mon}</div></div>
                            <div className="aa-histrow__main">
                              <div className="aa-histrow__title">{h.title}</div>
                              <div className="aa-histrow__sub">{h.sub}</div>
                            </div>
                            <span className="aa-ring" style={{ background: `color-mix(in srgb, ${ringColor(h.pct)} 16%, transparent)`, color: ringColor(h.pct) }}>{h.pct}%</span>
                          </div>
                        );
                      })}
                    </div>
                  ) : null}
                </div>
              );
            })}
          </div>
        )}
      </div>
    </React.Fragment>
  );
}

/* ---------- Profile ---------- */
function ProfileScreen({ profile, streak, week, onUpdate, onSignOut }) {
  const { MFLIcons } = window;
  const [editing, setEditing] = React.useState(false);
  const [name, setName] = React.useState(profile.name);
  const [level, setLevel] = React.useState(profile.level);
  const save = () => { onUpdate({ name: (name || "").trim() || profile.name, level: (level || "").trim() }); setEditing(false); };
  const cancel = () => { setName(profile.name); setLevel(profile.level); setEditing(false); };
  return (
    <React.Fragment>
      <AppBar title="Profile" right={MFLIcons.settings({ width: 19, height: 19 })} />
      <div className="aa-page">
        <div className="aa-profhead">
          <Avatar name={profile.name} size="xl" ring />
          {editing ? (
            <div className="aa-edit">
              <Input label="Name" value={name} onChange={(e) => setName(e.target.value)} />
              <Input label="Level / weight" value={level} onChange={(e) => setLevel(e.target.value)} />
              <div className="aa-edit__row">
                <Button variant="primary" onClick={save}>Save</Button>
                <Button variant="ghost" onClick={cancel}>Cancel</Button>
              </div>
            </div>
          ) : (
            <React.Fragment>
              <div className="nm">{profile.name}</div>
              <div className="lv">{profile.level}{profile.coach ? " · " + profile.coach : ""}</div>
              <button className="aa-textbtn" onClick={() => setEditing(true)}>Edit profile</button>
            </React.Fragment>
          )}
        </div>
        <div className="aa-summary">
          <Card><Stat size="sm" value={streak} unit="day" label="Streak" /></Card>
          <Card><Stat size="sm" value={week.rounds} label="Rounds / wk" /></Card>
          <Card><Stat size="sm" value={week.adherence} unit="%" label="Adherence" /></Card>
        </div>
        <Button variant="secondary" fullWidth leftIcon={MFLIcons.logout({ width: 18, height: 18 })} onClick={onSignOut}>
          Sign out
        </Button>
      </div>
    </React.Fragment>
  );
}

Object.assign(window, {
  AppBar, TabBar, RoundItem, RoundTimer, RoundLog, DailyBell,
  TodayScreen, RestDayScreen, SessionScreen, ScheduleScreen, WeekScreen, MessagesScreen, HistoryScreen, ProfileScreen,
  MFL_parseMin: parseMin,
});
