// fc-driftwatch.jsx, the early-warning lifecycle tier (§9.5). The confirmed
// 7-day verdict (behind/unsafe) + the Change-Plan flow already exist; this is the
// SOFT layer that fires first: a CUSUM of daily deviation vs the cycle-adjusted
// plan catches a consistent creep in ~2–3 days, well before a 7-day rate could.
// It is deliberately quiet and NON-RED — a heads-up, never a re-plan.
//   DriftWatchCard   · the nudge itself (behind / fast / clear), data-driven
//   DriftWatchToday  · the card in context on the dashboard, so its calm register
//                      vs. the confirmed verdict is legible
// Reads window.driftWatch(paceKey); demo-overridable for the late-tightening state.

const { Phone: DPhone, StatusBar: DStatusBar, HomeIndicator: DHome, LargeTitle: DLargeTitle,
        TabBar: DTabBar, GearButton: DGear, DashBanner: DDashBanner, Eyebrow: DEyebrow,
        Card: DCard, CoachTip: DCoachTip } = window;

// CUSUM accumulation meter — shows how far the drift has built toward the
// decision limit `h`. Amber fill, hollow track, a tick + label at the limit.
function CusumMeter({ pct = 0.7, tripped = false, label = 'heads-up at' }) {
  const tone = tripped ? 'var(--t-amber)' : 'var(--ink-3)';
  return (
    <div style={{ marginTop: 16 }}>
      <div style={{ position: 'relative', height: 8, background: 'var(--rule)', borderRadius: 4, overflow: 'visible' }}>
        <div style={{ width: `${Math.max(4, Math.min(100, pct * 100))}%`, height: '100%', background: tone, borderRadius: 4, transition: 'width 240ms ease' }} />
        {/* decision-limit tick */}
        <div style={{ position: 'absolute', top: -3, bottom: -3, left: '100%', width: 2, background: 'var(--ink-3)', transform: 'translateX(-2px)', borderRadius: 1 }} />
      </div>
      <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 7 }}>
        <span style={{ fontFamily: 'var(--mono)', fontSize: 9.5, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--ink-3)', fontWeight: 600 }}>drift building</span>
        <span style={{ fontFamily: 'var(--mono)', fontSize: 9.5, letterSpacing: '0.08em', textTransform: 'uppercase', color: tone, fontWeight: 700 }}>{label}</span>
      </div>
    </div>
  );
}

// Pull the live drift read, allow explicit overrides for the demo states.
function driftRead(paceKey, over) {
  let d = {};
  try { d = (window.driftWatch ? window.driftWatch(paceKey) : {}) || {}; } catch (e) { d = {}; }
  return { status: 'behind', days: 3, pct: 1, tightened: false, ...d, ...(over || {}) };
}

const COPY = {
  behind: {
    chip: 'Drift watch',
    headline: 'You’ve crept above plan three mornings running.',
    body: 'Not one heavy day — a steady drift. Catching it now means a small nudge instead of a hard correction later. Tighten your food a touch and we’ll keep watching.',
    meterLabel: 'heads-up at',
  },
  fast: {
    chip: 'Drift watch',
    headline: 'You’re sliding under plan a little fast.',
    body: 'Three mornings trending below the line. Nothing alarming, but losing quicker than planned eats into fight-night power. Add a bit back and hold the line.',
    meterLabel: 'heads-up at',
  },
  clear: {
    chip: 'Drift watch',
    headline: 'Holding the line — no drift.',
    body: 'Your last fortnight tracks the plan within normal day-to-day water noise. Nothing to do. We surface this only when a consistent creep starts.',
    meterLabel: 'limit',
  },
};

// The nudge. Quiet amber when active, neutral when clear. Always carries the
// "early read · not a verdict" line so it never reads as the confirmed call.
function DriftWatchCard({ paceKey = 'trailing', variant, override, late = false }) {
  const dir = variant || (paceKey === 'tooFast' ? 'fast' : paceKey === 'onTrack' ? 'clear' : 'behind');
  const d = driftRead(paceKey, override);
  const active = dir !== 'clear';
  const c = COPY[dir];
  const tone = active ? 'var(--t-amber)' : 'var(--t-green)';
  const soft = active ? 'var(--t-amber-soft)' : 'var(--t-green-soft)';
  const days = override?.days ?? d.days ?? 3;
  const pct = override?.pct ?? (active ? Math.min(1, d.pct || 1) : 0.4);
  return (
    <div style={{ background: soft, border: `1px solid color-mix(in srgb, ${tone} 26%, transparent)`, borderRadius: 'var(--radius)', padding: '18px 19px' }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 9 }}>
          {/* radar/eye glyph — watching, not warning */}
          <span style={{ width: 22, height: 22, color: tone, display: 'flex', flexShrink: 0 }}>
            <svg width="22" height="22" viewBox="0 0 24 24" fill="none"><path d="M2 12 C5 6 9 4 12 4 S19 6 22 12 C19 18 15 20 12 20 S5 18 2 12Z" stroke="currentColor" strokeWidth="1.5"/><circle cx="12" cy="12" r="3" stroke="currentColor" strokeWidth="1.5"/></svg>
          </span>
          <span style={{ fontFamily: 'var(--display)', fontSize: 11, letterSpacing: '0.16em', textTransform: 'uppercase', fontWeight: 600, color: tone }}>{c.chip}</span>
        </div>
        {active && <span style={{ fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--ink-3)', fontWeight: 700 }}>{days}-day creep</span>}
      </div>

      <div style={{ fontFamily: 'var(--sans)', fontSize: 17, fontWeight: 700, lineHeight: 1.25, color: 'var(--ink)', marginTop: 12, textWrap: 'balance' }}>{c.headline}</div>
      <div style={{ fontFamily: 'var(--sans)', fontSize: 13.5, lineHeight: 1.55, color: 'var(--ink-2)', marginTop: 8, textWrap: 'pretty' }}>{c.body}</div>

      {active && <CusumMeter pct={pct} tripped label={c.meterLabel} />}

      {late && active && (
        <div style={{ fontFamily: 'var(--sans)', fontSize: 12.5, lineHeight: 1.5, color: 'var(--ink-2)', marginTop: 14, padding: '11px 13px', background: 'var(--paper)', borderRadius: 'var(--radius-ctl)', textWrap: 'pretty' }}>
          <b style={{ color: 'var(--ink)' }}>Inside two weeks out, we watch tighter.</b> This tripped on a smaller drift than it would early in camp — lost days cost more the closer you are to weigh-in.
        </div>
      )}

      {/* the line that keeps it a heads-up, not the verdict */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 14, paddingTop: 13, borderTop: '1px solid color-mix(in srgb, var(--ink) 9%, transparent)' }}>
        <svg width="14" height="14" viewBox="0 0 16 16" fill="none" style={{ flexShrink: 0 }}><circle cx="8" cy="8" r="7" stroke="var(--ink-3)" strokeWidth="1.3"/><line x1="8" y1="7" x2="8" y2="11.5" stroke="var(--ink-3)" strokeWidth="1.4" strokeLinecap="round"/><circle cx="8" cy="4.6" r="0.9" fill="var(--ink-3)"/></svg>
        <span style={{ fontFamily: 'var(--sans)', fontSize: 12, lineHeight: 1.4, color: 'var(--ink-3)', textWrap: 'pretty' }}>Early read — not a verdict. Your weekly pace check still has the final say.</span>
      </div>
    </div>
  );
}

// In-context: the drift-watch card sitting on Today, so its calm register reads
// against the hero number. This is the moment BEFORE the 7-day verdict confirms.
function DriftWatchToday({ styleKey = 'balanced', variant = 'behind' }) {
  const paceKey = variant === 'fast' ? 'tooFast' : 'trailing';
  return (
    <DPhone styleKey={styleKey} label={`Today · Drift watch (${variant})`}>
      <DStatusBar />
      <DDashBanner tone="ink" label="IN CAMP · DAY 33" meta="17 DAYS OUT" />
      <DLargeTitle title="Today" trailing={<DGear />} />
      <div style={{ flex: 1, padding: '2px 20px 24px', display: 'flex', flexDirection: 'column', gap: 18 }}>
        <div>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, marginTop: 4 }}>
            <span style={{ fontFamily: 'var(--num)', fontWeight: 300, fontSize: 100, lineHeight: 0.82, letterSpacing: '-0.035em', color: 'var(--ink)' }}>{variant === 'fast' ? '75.1' : '76.4'}</span>
            <span style={{ fontFamily: 'var(--mono)', fontSize: 13, letterSpacing: '0.16em', color: 'var(--ink-3)', fontWeight: 600 }}>KG</span>
          </div>
          <div style={{ fontFamily: 'var(--mono)', fontSize: 11.5, letterSpacing: '0.13em', textTransform: 'uppercase', color: 'var(--ink-3)', fontWeight: 700, marginTop: 13 }}>
            Trend · {variant === 'fast' ? '0.3 kg under plan' : '0.3 kg over plan'}
          </div>
        </div>
        <DriftWatchCard variant={variant} paceKey={paceKey} />
        {/* the still-quiet pace row underneath — verdict has NOT flipped yet */}
        <div style={{ background: 'var(--paper)', borderRadius: 'var(--radius)', boxShadow: 'var(--card-shadow)', border: 'var(--card-border)', padding: '16px 18px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
          <div>
            <div style={{ fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.1em', textTransform: 'uppercase', color: 'var(--ink-3)', fontWeight: 600 }}>7-day pace</div>
            <div style={{ fontFamily: 'var(--sans)', fontSize: 15.5, fontWeight: 600, color: 'var(--ink)', marginTop: 4 }}>Still on plan</div>
          </div>
          <span style={{ fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: '0.04em', color: 'var(--t-green)', fontWeight: 700 }}>{variant === 'fast' ? '0.78 %/wk' : '0.62 %/wk'}</span>
        </div>
      </div>
      <DTabBar active="home" /><DHome />
    </DPhone>
  );
}

Object.assign(window, { DriftWatchCard, DriftWatchToday });
