// tracker.jsx — PAGE 2: The Tracker (habit grid + claim)
const { useRef: useRefT, useEffect: useEffectT, useState: useStateT } = React;

const TOTAL = 70;

/* Single reward: the full $50 unlocks at Day 70. No staged payouts. */
const REWARD_TOTAL = 50;

function currentStreak(checkedSet, day) {
  // consecutive checked days ending at the most recent checked day up to `day`
  let streak = 0;
  for (let d = day; d >= 1; d--) {
    if (checkedSet.has(d)) streak++;else
    if (d === day) continue; // today not yet checked doesn't break a prior streak
    else break;
  }
  return streak;
}

/* Add-to-Home-Screen popup (mobile only, iPhone how-to). Appears 15s after the
   tracker loads — not always on page. Dismiss persists so it won't nag again. */
const A2HS_KEY = "hyro70.a2hs.dismissed.v1";
const A2HS_DELAY_MS = 15000;
function AddToHomeScreen({ force, enabled }) {
  // eligible = mobile-ish, not already installed, not previously dismissed
  const eligible = (() => {
    try {
      const standalone = window.navigator.standalone === true ||
        (window.matchMedia && window.matchMedia("(display-mode: standalone)").matches);
      if (standalone) return false;
      if (!force && localStorage.getItem(A2HS_KEY) === "1") return false;
      return !!force || !!enabled;
    } catch (e) { return true; }
  })();
  const [show, setShow] = useStateT(false);

  useEffectT(() => {
    if (!eligible) return;
    const id = setTimeout(() => setShow(true), force ? 250 : A2HS_DELAY_MS);
    return () => clearTimeout(id);
  }, [eligible, force]);

  if (!eligible || !show) return null;
  function dismiss() {
    try { localStorage.setItem(A2HS_KEY, "1"); } catch (e) {}
    setShow(false);
  }
  if (force) {
    const inApp = /Slack|Instagram|FBAN|FBAV|GSA|CriOS|FxiOS|EdgiOS/i.test(navigator.userAgent);
    const StepVisual = ({ type }) => type === "menu" ? (
      <div className="install-step-visual safari-bar" aria-hidden="true"><i>‹</i><i>›</i><i className="safari-dots">•••</i></div>
    ) : type === "share" ? (
      <div className="install-step-visual ios-row" aria-hidden="true"><i className="ios-share">↑</i><span>Share</span><b>›</b></div>
    ) : type === "open" ? (
      <div className="install-step-visual ios-row" aria-hidden="true"><span className="safari-compass">◢</span><span>Open in Safari</span><b>›</b></div>
    ) : (
      <div className="install-step-visual ios-row" aria-hidden="true"><i className="ios-add">＋</i><span>Add to Home Screen</span><b>›</b></div>
    );
    return (
      <div className="install-gate" role="dialog" aria-modal="true" aria-label="Install Hyro Challenge">
        <div className="install-shell">
          <header className="install-head">
            <div className="install-app-icon"><img src="assets/icon-192.png" alt="Hyro Challenge app icon" /></div>
            <div><span className="install-kicker">Free Hyro app</span><h1>Make every day count.</h1></div>
          </header>

          <div className="install-preview" aria-label="Preview of the Hyro Challenge app">
            <div className="install-phone">
              <div className="install-phone-bar"><span>9:41</span><i></i></div>
              <div className="install-phone-screen"><img src="assets/tracker-app-preview.png" alt="The real Hyro Challenge tracker showing a 13 day streak" /></div>
            </div>
            <div className="install-notification">
              <img src="assets/icon-192.png" alt="" />
              <div><b>HYRO CHALLENGE</b><strong>Time to hydrate 💧</strong><span>Keep your streak alive.</span></div>
              <small>now</small>
            </div>
          </div>

          <div className="install-benefits">
            <span><i>✓</i> Daily check-ins</span><span><i>✓</i> Hydration reminders</span><span><i>✓</i> Works like an app</span>
          </div>

          <section className="install-how">
            <span className="install-how-label">Install in three taps</span>
            {inApp ? <div className="install-steps">
              <div className="install-step active"><span>1</span><StepVisual type="open" /><div><strong>Open in Safari</strong><p>Open this page in Apple's Safari app.</p></div></div>
              <div className="install-step"><span>2</span><StepVisual type="share" /><div><strong>Tap Share</strong><p>Tap <b>•••</b>, then choose <b>Share</b>.</p></div></div>
              <div className="install-step"><span>3</span><StepVisual type="add" /><div><strong>Add the app</strong><p>Choose <b>Add to Home Screen</b>, then <b>Add</b>.</p></div></div>
            </div> : <div className="install-steps">
              <div className="install-step active"><span>1</span><StepVisual type="menu" /><div><strong>Tap the ••• button</strong><p>Find it at the bottom-right of Safari.</p></div></div>
              <div className="install-step"><span>2</span><StepVisual type="share" /><div><strong>Tap Share</strong><p>It's the first option in the menu.</p></div></div>
              <div className="install-step"><span>3</span><StepVisual type="add" /><div><strong>Add to Home Screen</strong><p>Scroll down, tap it, then tap <b>Add</b>.</p></div></div>
            </div>}
            <div className="install-ready"><span className="install-pulse"></span> Open the new Hyro icon when you're done.</div>
          </section>
        </div>
      </div>
    );
  }
  return (
    <div className="a2hs-back show" onClick={dismiss} role="dialog" aria-modal="true" aria-label="Add to home screen">
      <div className="a2hs-pop" onClick={(e) => e.stopPropagation()}>
        <button className="a2hs-close" onClick={dismiss} aria-label="Dismiss">×</button>
        <div className="a2hs-ic">{Icon.drop({ style: { width: 24, height: 24, stroke: "#fff", fill: "none" } })}</div>
        <h4>Keep it one tap away</h4>
        <p>Add this to your home screen so checking in each day is one tap.</p>
        <ol className="a2hs-steps">
          <li>Tap the <b>Share</b> icon <span className="a2hs-share" aria-hidden="true">↑</span> at the bottom of Safari</li>
          <li>Scroll and tap <b>Add to Home Screen</b></li>
          <li>Tap <b>Add</b> — done</li>
        </ol>
        <button className="a2hs-got" onClick={dismiss}>Got it</button>
      </div>
    </div>);

}

/* Live countdown to the next day (local midnight). Updates every second. */
function NextDayCountdown({ currentDay }) {
  const [now, setNow] = useStateT(() => new Date());
  useEffectT(() => {
    const id = setInterval(() => setNow(new Date()), 1000);
    return () => clearInterval(id);
  }, []);
  if (currentDay >= TOTAL) return null; // no countdown once finished
  const next = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1, 0, 0, 0, 0);
  let s = Math.max(0, Math.floor((next - now) / 1000));
  const hh = String(Math.floor(s / 3600)).padStart(2, "0");
  const mm = String(Math.floor((s % 3600) / 60)).padStart(2, "0");
  const ss = String(s % 60).padStart(2, "0");
  return (
    <div className="tk-timer" aria-label="Time until your next day unlocks">
      <span className="tk-timer-lbl">Next day in</span>
      <span className="tk-timer-clock">{hh}:{mm}:{ss}</span>
    </div>);

}

function Box({ day, state, tappable, justChecked, onTap }) {
  return (
    <div
      className={"bottle-cell " + state + (tappable ? " tappable" : "") + (justChecked ? " just-checked" : "")}
      onClick={tappable ? () => onTap(day) : undefined}
      role={tappable ? "button" : undefined}
      aria-label={`Day ${day}${state === "done" ? ", done" : ""}`}>
      
      <Bottle state={state} />
      <span className="bottle-day">{day}</span>
    </div>);

}

function ClaimCard({ currentDay, claimed, onClaim, onRetake, member }) {
  const unlocked = currentDay >= TOTAL;
  const toGo = TOTAL - currentDay;
  const [open, setOpen] = useStateT(false);
  const [name, setName] = useStateT(member.firstName || "");
  const [email, setEmail] = useStateT(member.email || "");
  const [err, setErr] = useStateT("");

  function submitClaim(e) {
    e.preventDefault();
    if (!name.trim()) {setErr("Add your name");return;}
    if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email.trim())) {setErr("That email does not look right");return;}
    setErr("");onClaim(name.trim(), email.trim());
  }

  return (
    <div className={"claim-card" + (unlocked ? " unlocked" : "")}>
      <span className="bdg" style={{ fontFamily: "var(--font-display)", textTransform: "uppercase", fontSize: 12, letterSpacing: "0.05em", opacity: 0.85 }}>The reward</span>
      <div className="amt lemon">$50</div>
      <h4>{claimed ? "Claim submitted" : unlocked ? "Claim your $50" : "Your $50 at Day 70"}</h4>

      {claimed ?
      <p>Awesome work! We've just dropped $50 Hyro credit into your account. Happy hydrating!
</p> : unlocked ?
      <p>Wow! You finished the 70-day challenge!
Confirm your details to claim your reward.
      </p> : <p>Drink Hyro every day and check off your boxes. Finish all 70 days and the full $50 Hyro credit is yours.</p>
      }

      {claimed ?
      <>
        <span className="claim-lockrow">{Icon.check({ style: { width: 14, height: 14, stroke: "currentColor", fill: "none" } })} Reward claimed</span>
        <button type="button" className="claim-retake" onClick={onRetake}>{Icon.refresh({ style: { width: 15, height: 15, stroke: "currentColor", fill: "none" } })} Re-take the 70-Day Challenge</button>
      </> :
      unlocked ?
      open ?
      <form className="claim-form" onSubmit={submitClaim}>
            <input className="claim-input" value={name} onChange={(e) => setName(e.target.value)} placeholder="Your name" autoComplete="name" />
            <input className="claim-input" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="you@email.com" type="email" autoComplete="email" />
            {err && <div className="claim-err">{err}</div>}
            <button type="submit" className="cta on-red block">Submit my claim</button>
            <button type="button" className="claim-cancel" onClick={() => setOpen(false)}>Cancel</button>
          </form> :

      <button className="cta on-red block" onClick={() => setOpen(true)}>Claim my $50</button> :


      <span className="claim-lockrow">{Icon.lock({ style: { width: 14, height: 14, stroke: "currentColor", fill: "none" } })} $50 unlocks at Day 70 &middot; {toGo} to go</span>
      }
    </div>);

}

const PUSH_DEFAULTS = [
  { time: "09:00", title: "Time to get hydrated", body: "Start your day with Hyro and keep your streak alive.", cta: "GET HYDRATED", enabled: true },
  { time: "14:00", title: "Time to get hydrated", body: "Time for a Hyro top-up. Your body will thank you.", cta: "GET HYDRATED", enabled: true }
];

function b64ToBytes(value) {
  const pad = "=".repeat((4 - value.length % 4) % 4);
  const raw = atob((value + pad).replace(/-/g, "+").replace(/_/g, "/"));
  return Uint8Array.from([...raw].map(c => c.charCodeAt(0)));
}

function RemindersPage({ member, onBack }) {
  const [openIndex, setOpenIndex] = useStateT(-1);
  const [busy, setBusy] = useStateT(false);
  const [subscribed, setSubscribed] = useStateT(false);
  const [reminders, setReminders] = useStateT(PUSH_DEFAULTS);
  const [message, setMessage] = useStateT("");
  const installed = window.navigator.standalone === true || (window.matchMedia && window.matchMedia("(display-mode: standalone)").matches);
  const isIos = /iphone|ipad|ipod/i.test(navigator.userAgent);
  const supported = "serviceWorker" in navigator && "PushManager" in window && "Notification" in window;
  const timezone = (() => { try { return Intl.DateTimeFormat().resolvedOptions().timeZone || "Australia/Sydney"; } catch (_) { return "Australia/Sydney"; } })();

  useEffectT(() => {
    if (!member.email) return;
    fetch("/api/push/settings?email=" + encodeURIComponent(member.email))
      .then(r => r.json()).then(d => {
        if (!d || !d.ok) return;
        setSubscribed(!!d.subscribed);
        if (Array.isArray(d.reminders) && d.reminders.length) setReminders(d.reminders.map(r => ({ ...r, title: "Time to get hydrated", cta: "GET HYDRATED", enabled: true })));
      }).catch(() => {});
  }, [member.email]);

  async function enable() {
    setMessage("");
    if (!supported) { setMessage("Push reminders are not supported in this browser."); return; }
    if (isIos && !installed) { setMessage("Add Hyro Challenge to your Home Screen first, then open the app and switch reminders on."); return; }
    setBusy(true);
    try {
      const reg = await navigator.serviceWorker.ready;
      const permission = await Notification.requestPermission();
      if (permission !== "granted") throw new Error("permission");
      const key = await fetch("/api/push/public-key").then(r => r.json());
      if (!key.ok) throw new Error("config");
      let subscription = await reg.pushManager.getSubscription();
      if (!subscription) subscription = await reg.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: b64ToBytes(key.publicKey) });
      const result = await fetch("/api/push/settings", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email: member.email, firstName: member.firstName, timezone, subscription: subscription.toJSON(), reminders }) }).then(r => r.json());
      if (!result.ok) throw new Error("save");
      setSubscribed(true); setMessage("Reminders are on. Your hydration nudges are ready.");
    } catch (e) {
      setMessage(e.message === "permission" ? "Notifications are blocked. Allow them in your phone settings, then try again." : "We couldn't switch reminders on. Please try again.");
    } finally { setBusy(false); }
  }

  async function save() {
    setBusy(true); setMessage("");
    try {
      const result = await fetch("/api/push/settings", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email: member.email, firstName: member.firstName, timezone, reminders }) }).then(r => r.json());
      if (!result.ok) throw new Error();
      setMessage("Saved. Your reminders now run on your phone's local time.");
    } catch (_) { setMessage("We couldn't save those reminders. Please try again."); }
    finally { setBusy(false); }
  }

  async function disable() {
    setBusy(true); setMessage("");
    try {
      const reg = await navigator.serviceWorker.ready;
      const sub = await reg.pushManager.getSubscription();
      if (sub) await sub.unsubscribe();
      await fetch("/api/push/settings", { method: "DELETE", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email: member.email, firstName: member.firstName, timezone }) });
      setSubscribed(false); setMessage("Reminders are off.");
    } catch (_) { setMessage("We couldn't turn reminders off. Please try again."); }
    finally { setBusy(false); }
  }

  function updateMessage(i, value) {
    const twoLines = value.split("\n").slice(0, 2).join("\n").slice(0, 100);
    setReminders(prev => prev.map((r, x) => x === i ? { ...r, body: twoLines, title: "Time to get hydrated", cta: "GET HYDRATED", enabled: true } : r));
  }
  function updateTime(i, value) { setReminders(prev => prev.map((r, x) => x === i ? { ...r, time: value, title: "Time to get hydrated", cta: "GET HYDRATED", enabled: true } : r)); }
  function add() {
    if (reminders.length >= 5) return;
    const next = reminders.length;
    setReminders(prev => [...prev, { time: "18:00", title: "Time to get hydrated", body: "Time for your next Hyro.", cta: "GET HYDRATED", enabled: true }]);
    setOpenIndex(next);
  }
  function remove(i) {
    if (reminders.length <= 1) return;
    setReminders(prev => prev.filter((_, x) => x !== i));
    setOpenIndex(-1);
  }

  return <div className="reminders-page" data-screen-label="Reminders">
    <header className="reminders-hero">
      <div className="reminders-shell">
        <button className="reminders-back" onClick={onBack} aria-label="Back to tracker">‹ <span>Tracker</span></button>
        <div className="reminders-bell" aria-hidden="true">{Icon.bell ? Icon.bell({ style: { width: 28, height: 28, stroke: "#fff", fill: "none" } }) : "✦"}</div>
        <span className="reminders-eyebrow">Your hydration rhythm</span>
        <h1>Never miss your Hyro.</h1>
        <p>Set the moments that work for you. We’ll handle the nudge.</p>
        <div className="reminders-summary"><strong>{reminders.length}</strong><span>daily reminder{reminders.length === 1 ? "" : "s"}</span><i></i><span>{timezone.replace(/_/g, " ")}</span></div>
      </div>
    </header>
    <main className="reminders-shell reminders-main">
      {message && <div className="reminders-toast" role="status">{message}</div>}
      {!subscribed && isIos && !installed && <div className="reminders-install-note"><strong>One quick step first</strong><span>Install Hyro Challenge on your Home Screen to unlock reminders.</span><a href="/?install=1">Install the app</a></div>}
      <div className="reminders-list">
        {reminders.map((r, i) => {
          const expanded = openIndex === i;
          return <article className={"reminder-row" + (expanded ? " expanded" : "")} key={i}>
            <button className="reminder-row-head" onClick={() => setOpenIndex(expanded ? -1 : i)} aria-expanded={expanded}>
              <span className="reminder-number">0{i + 1}</span>
              <span className="reminder-time">{formatReminderTime(r.time)}</span>
              <span className="reminder-preview">{r.body}</span>
              <span className="reminder-chevron">⌄</span>
            </button>
            {expanded && <div className="reminder-editor">
              <label className="reminder-field time"><span>Time</span><input type="time" value={r.time} onChange={e => updateTime(i, e.target.value)} /></label>
              <label className="reminder-field message"><span>Message <small>2 lines max</small></span><textarea rows="2" maxLength="100" value={r.body} onChange={e => updateMessage(i, e.target.value)} /></label>
              <div className="reminder-fixed-cta"><span>Notification button</span><strong>GET HYDRATED</strong></div>
              {reminders.length > 1 && <button className="reminder-delete" onClick={() => remove(i)}>Remove reminder</button>}
            </div>}
          </article>;
        })}
      </div>
      {reminders.length < 5 && <button className="reminders-add" onClick={add}><span>+</span> Add another reminder</button>}
      <button className="reminders-save" disabled={busy} onClick={subscribed ? save : enable}>{busy ? "Saving…" : subscribed ? "Save reminders" : "Turn on reminders"}</button>
      {subscribed && <button className="reminders-off" disabled={busy} onClick={disable}>Turn off all reminders</button>}
      <p className="reminders-footnote">You can change your reminder times and messages whenever you like.</p>
    </main>
  </div>;
}

function formatReminderTime(value) {
  const parts = String(value || "09:00").split(":");
  const hour = Number(parts[0]);
  return `${hour % 12 || 12}:${parts[1]} ${hour >= 12 ? "PM" : "AM"}`;
}

function Tracker({ member, currentDay, checked, onToggle, claimed, onClaim, onRetake, justChecked, onReminders }) {
  const checkedSet = new Set(checked);
  const checkedCount = checked.length;
  const todayWeekRef = useRefT(null);
  const streak = currentStreak(checkedSet, currentDay);
  const toGo = Math.max(0, TOTAL - currentDay);
  const dayProgress = Math.min(100, currentDay / TOTAL * 100);
  const todayChecked = checkedSet.has(currentDay);

  // auto-centre today's week (no scrollIntoView)
  useEffectT(() => {
    const el = todayWeekRef.current;
    if (!el) return;
    const id = setTimeout(() => {
      const r = el.getBoundingClientRect();
      const target = window.scrollY + r.top - Math.max(150, window.innerHeight * 0.32);
      window.scrollTo({ top: Math.max(0, target), behavior: "smooth" });
    }, 350);
    return () => clearTimeout(id);
  }, [currentDay]);

  function stateFor(day) {
    if (checkedSet.has(day)) return "done";
    if (day === currentDay) return "today";
    if (day < currentDay) return "missable";
    return "future";
  }
  function tappableFor(day) {
    return day <= currentDay; // today + recoverable past days
  }

  const weeks = Array.from({ length: 10 }, (_, w) =>
  Array.from({ length: 7 }, (_, d) => w * 7 + d + 1)
  );
  const todayWeekIdx = Math.floor((currentDay - 1) / 7);

  function jumpToday() {
    const el = todayWeekRef.current;
    if (!el) return;
    const r = el.getBoundingClientRect();
    window.scrollTo({ top: Math.max(0, window.scrollY + r.top - 150), behavior: "smooth" });
  }

  return (
    <div className="tracker-page" data-screen-label="Tracker">
      {/* TOP */}
      <div className="tk-top">
        <div className="wrap">
          <div className="tk-lockup">
            <img src="assets/logos/hyro-wordmark-white.png" alt="Hyro" />
          </div>
          <button className="tk-reminders-link" onClick={onReminders}><span className="tk-reminders-icon">●</span><span>Reminders</span><b>›</b></button>
          <h1 className="tk-greeting">Welcome to your tracker, <em>{member.firstName || "legend"}</em></h1>
          <div className="tk-stat-row">
            <span className="tk-stat-pills">
              <span className="tk-streak"><span className="streak-emoji" aria-hidden="true">🔥</span> {streak} day streak</span>
              <NextDayCountdown currentDay={currentDay} />
            </span>
          </div>
          <div className="tk-progress"><div style={{ width: dayProgress + "%" }}></div></div>
          <p className="tk-countdown"><b>$50</b> at Day 70 &middot; {toGo} {toGo === 1 ? "day" : "days"} to go &middot; {checkedCount}/70 days hydrated</p>
          <div className="tk-sub-note">
            <span className="tk-sub-ic">{Icon.check({ style: { width: 14, height: 14, stroke: "currentColor", fill: "none" } })}</span>
            <span><strong>Reminder:</strong> Keep your Hyro subscription active right through to Day 70 to claim your reward.</span>
          </div>
        </div>
      </div>

      {/* BODY */}
      <div className="wrap tk-body">
        <div className="tk-layout">
          <div className="tk-grid-col">
            {weeks.map((days, w) => {
              const isTodayWeek = w === todayWeekIdx;
              const row =
              <div className="wk" key={"wk" + w} ref={isTodayWeek ? todayWeekRef : null}>
                  <div className="wk-head">
                    <span className="wk-lbl">Week {w + 1}{isTodayWeek ? " · you are here" : ""}</span>
                  </div>
                  <div className="wk-row">
                    {days.map((day) =>
                  <Box key={day} day={day} state={stateFor(day)}
                  tappable={tappableFor(day)} justChecked={justChecked === day}
                  onTap={onToggle} />
                  )}
                  </div>
                </div>;

              return row;
            })}
            {/* claim card inline on mobile, right rail on desktop handled by order */}
            <div className="hide-desktop" style={{ marginTop: 8 }}>
              <ClaimCard currentDay={currentDay} claimed={claimed} onClaim={onClaim} onRetake={onRetake} member={member} />
            </div>
          </div>

          {/* right rail (desktop) */}
          <div className="hide-mobile">
            <ClaimCard currentDay={currentDay} claimed={claimed} onClaim={onClaim} onRetake={onRetake} member={member} />
          </div>
        </div>
        <p className="tk-autoship-note"><em>Note: Your Hyro AutoShip must remain active for the full 70 days to be eligible to claim.</em></p>
      </div>

      {/* sticky check today (mobile) */}
      <div className="check-bar">
        <div className="info">
          {todayChecked ?
          <><b>Day {currentDay} done.</b> See you tomorrow.</> :
          <>Drank your Hyro? <b>Tick Day {currentDay}.</b></>}
        </div>
        {todayChecked ?
        <button className="cta" style={{ background: "var(--hyro-ink)", borderColor: "var(--hyro-ink)" }} onClick={jumpToday}>Day {currentDay} ✓</button> :
        <button className="cta" onClick={() => onToggle(currentDay)}>Check today</button>}
      </div>
    </div>);

}

window.Tracker = Tracker;
