// fc-cut.jsx — two new OnWeight chart types.
//
//  FCWaterCutCard — the fight-week water cut + rehydration. The classic combat
//    curve: a sharp CUT down to the weigh-in limit, then the REBUILD back up to
//    fight weight. Limit line is the anchor; cut leg is red (stress), rebuild leg
//    green (recovery). Answers "how much to sweat off, and how much to put back".
//
//  FCNoiseCard — daily noise vs the trend. Raw weigh-in dots scattered in a soft
//    ±band around the smooth trend, so a day UP reads as normal, not failure.
//
// Same FC type system (var(--num)/--display, tones). kg, tnum.

function _cr2(pts, k = 0.5) {
  if (pts.length < 2) return '';
  let d = `M ${pts[0][0].toFixed(2)} ${pts[0][1].toFixed(2)}`;
  for (let i = 0; i < pts.length - 1; i++) {
    const p0 = pts[Math.max(0, i - 1)], p1 = pts[i], p2 = pts[i + 1], p3 = pts[Math.min(pts.length - 1, i + 2)];
    d += ` C ${(p1[0] + (p2[0] - p0[0]) * k / 3).toFixed(2)} ${(p1[1] + (p2[1] - p0[1]) * k / 3).toFixed(2)}, ${(p2[0] - (p3[0] - p1[0]) * k / 3).toFixed(2)} ${(p2[1] - (p3[1] - p1[1]) * k / 3).toFixed(2)}, ${p2[0].toFixed(2)} ${p2[1].toFixed(2)}`;
  }
  return d;
}

// ── WATER CUT ────────────────────────────────────────────────────────────────
// timeline: [hoursFromStart, kg]; weigh-in is the low point at/under the limit.
const _CUT = [
  [0, 76.2], [14, 75.6], [24, 75.0], [30, 74.6], [35, 74.3],   // Thu 6a → Fri 5pm (weigh-in)
  [37, 75.4], [41, 76.8], [52, 77.8], [61, 78.4],              // rehydrate → Sat 7pm (fight)
];
const _CUT_WI = 4;     // index of weigh-in point
const _CUT_LIMIT = 74.4;

function FCWaterCutChart({ width = 360, height = 196 }) {
  const pts = _CUT, wiI = _CUT_WI;
  const W = width, H = height, padL = 8, padR = 30, padT = 22, padB = 32;
  const innerW = W - padL - padR, innerH = H - padT - padB;
  const tMax = pts[pts.length - 1][0];
  const ws = pts.map(p => p[1]);
  const yMin = Math.min(_CUT_LIMIT, ...ws) - 0.5, yMax = Math.max(...ws) + 0.6;
  const xS = (t) => padL + (t / tMax) * innerW;
  const yS = (w) => padT + ((yMax - w) / (yMax - yMin)) * innerH;
  const baseY = padT + innerH;
  const P = pts.map(p => [xS(p[0]), yS(p[1])]);
  const cutPath = _cr2(P.slice(0, wiI + 1), 0.5);
  const rebuildPath = _cr2(P.slice(wiI), 0.5);
  const wiX = P[wiI][0], wiY = P[wiI][1], limitY = yS(_CUT_LIMIT);
  const fight = P[P.length - 1];
  const ticks = [];
  for (let w = Math.ceil(yMin); w <= yMax; w++) ticks.push(w);
  const red = 'var(--t-red)', green = 'var(--t-green)';
  const uid = React.useId().replace(/:/g, '');

  return (
    <svg width={W} height={H} viewBox={`0 0 ${W} ${H}`} style={{ display: 'block', overflow: 'visible', shapeRendering: 'geometricPrecision' }} role="img"
      aria-label={`Fight-week water cut: down to ${pts[wiI][1]} kg at weigh-in under the ${_CUT_LIMIT} kg limit, then rehydrating to ${fightW()} kg for the fight.`}>
      {/* phase tints */}
      <rect x={padL} y={padT} width={wiX - padL} height={innerH} fill={red} opacity="0.05" />
      <rect x={wiX} y={padT} width={W - padR - wiX} height={innerH} fill={green} opacity="0.06" />

      {/* kg gridlines + right labels */}
      {ticks.map(w => (
        <g key={w}>
          <line x1={padL} x2={W - padR} y1={yS(w)} y2={yS(w)} stroke="var(--rule)" strokeWidth="0.6" opacity="0.5" />
          <text x={W - padR + 6} y={yS(w) + 3.4} fontFamily="var(--sans)" fontSize="10.5" fill="var(--ink-3)" style={{ fontFeatureSettings: '"tnum"' }}>{w}</text>
        </g>
      ))}

      {/* weigh-in limit */}
      <line x1={padL} x2={W - padR} y1={limitY} y2={limitY} stroke={red} strokeWidth="1.1" strokeDasharray="5 3" opacity="0.85" />
      <text x={padL} y={limitY - 5} fontFamily="var(--display)" fontSize="8.5" letterSpacing="0.14em" fontWeight="700" fill={red}>LIMIT {_CUT_LIMIT}</text>

      {/* weigh-in divider */}
      <line x1={wiX} x2={wiX} y1={padT} y2={baseY} stroke="var(--ink-3)" strokeWidth="0.6" strokeDasharray="2 3" opacity="0.45" />

      {/* cut (red) + rebuild (green) */}
      <path d={cutPath} fill="none" stroke={red} strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" />
      <path d={rebuildPath} fill="none" stroke={green} strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" />

      {/* markers */}
      <circle cx={wiX} cy={wiY} r="5.5" fill="var(--paper)" stroke={red} strokeWidth="2.2" />
      <circle cx={fight[0]} cy={fight[1]} r="5.5" fill={green} />

      {/* point value chips */}
      <text x={wiX} y={wiY + 18} textAnchor="middle" fontFamily="var(--num)" fontSize="13" fontWeight="600" fill={red} style={{ fontFeatureSettings: '"tnum"' }}>{pts[wiI][1].toFixed(1)}</text>
      <text x={fight[0]} y={fight[1] - 10} textAnchor="end" fontFamily="var(--num)" fontSize="13" fontWeight="600" fill={green} style={{ fontFeatureSettings: '"tnum"' }}>{fightW()}</text>

      {/* phase + time labels */}
      <g style={{ fontFeatureSettings: '"tnum"' }}>
        <text x={(padL + wiX) / 2} y={baseY + 14} textAnchor="middle" fontFamily="var(--display)" fontSize="9" letterSpacing="0.16em" fontWeight="700" fill={red}>CUT</text>
        <text x={(wiX + W - padR) / 2} y={baseY + 14} textAnchor="middle" fontFamily="var(--display)" fontSize="9" letterSpacing="0.16em" fontWeight="700" fill={green}>REHYDRATE</text>
        <text x={padL} y={baseY + 26} textAnchor="start" fontFamily="var(--sans)" fontSize="9.5" fill="var(--ink-3)">Thu</text>
        <text x={wiX} y={baseY + 26} textAnchor="middle" fontFamily="var(--sans)" fontSize="9.5" fill="var(--ink-2)" fontWeight="600">Fri · weigh-in</text>
        <text x={W - padR} y={baseY + 26} textAnchor="end" fontFamily="var(--sans)" fontSize="9.5" fill="var(--ink-3)">Sat · fight</text>
      </g>
    </svg>
  );
  function fightW() { return _CUT[_CUT.length - 1][1].toFixed(1); }
}

function FCWaterCutCard({ width = 360 }) {
  const start = _CUT[0][1], wi = _CUT[_CUT_WI][1], fight = _CUT[_CUT.length - 1][1];
  const toCut = start - wi, rebuild = fight - wi, pct = (toCut / start) * 100;
  const safe = pct <= 4;
  const tone = safe ? 'var(--t-green)' : 'var(--mustard-deep)';
  return (
    <div style={{ width: '100%' }}>
      <div style={{ fontFamily: 'var(--display)', fontSize: 10.5, letterSpacing: '0.18em', textTransform: 'uppercase', color: 'var(--accent)', fontWeight: 600 }}>Fight week · Water cut</div>
      <div style={{ fontFamily: 'var(--sans)', fontSize: 20, fontWeight: 700, lineHeight: 1.22, letterSpacing: '-0.01em', color: 'var(--ink)', marginTop: 8, textWrap: 'balance' }}>
        Sweat off {toCut.toFixed(1)} kg by Friday, then rebuild {rebuild.toFixed(1)}.
      </div>
      <div style={{ display: 'flex', gap: 20, marginTop: 18, paddingTop: 16, borderTop: '1px solid var(--rule)', alignItems: 'flex-start' }}>
        <div style={{ flex: 1 }}>
          <div style={{ fontFamily: 'var(--sans)', fontSize: 13.5, fontWeight: 600, color: 'var(--ink-2)' }}>To cut</div>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 4, marginTop: 7 }}><span style={{ fontFamily: 'var(--num)', fontWeight: 300, fontSize: 30, color: 'var(--t-red)', letterSpacing: '-0.02em' }}>{toCut.toFixed(1)}</span><span style={{ fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--ink-3)', fontWeight: 600 }}>kg</span></div>
        </div>
        <div style={{ flex: 1 }}>
          <div style={{ fontFamily: 'var(--sans)', fontSize: 13.5, fontWeight: 600, color: 'var(--ink-2)' }}>Rebuild</div>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 4, marginTop: 7 }}><span style={{ fontFamily: 'var(--num)', fontWeight: 300, fontSize: 30, color: 'var(--t-green)', letterSpacing: '-0.02em' }}>+{rebuild.toFixed(1)}</span><span style={{ fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--ink-3)', fontWeight: 600 }}>kg</span></div>
        </div>
        <div style={{ flexShrink: 0, paddingTop: 2 }}>
          <span style={{ fontFamily: 'var(--mono)', fontSize: 9.5, letterSpacing: '0.05em', textTransform: 'uppercase', color: tone, fontWeight: 700, border: `1px solid ${tone}`, borderRadius: 100, padding: '3px 9px', whiteSpace: 'nowrap' }}>{pct.toFixed(1)}% · {safe ? 'safe' : 'hard'}</span>
        </div>
      </div>
      <div style={{ marginTop: 16 }}><FCWaterCutChart width={width} /></div>
    </div>
  );
}

// ── NOISE vs TREND ─────────────────────────────────────────────────────────
const _SWING = 0.6;   // typical day-to-day swing (kg)

function FCNoiseChart({ paceKey = 'onTrack', width = 360, height = 184 }) {
  const p = window.computePace(paceKey), FC = window.FC;
  const startDay = Math.max(0, FC.todayDay - 13);
  const hist = p.hist.filter(h => h[0] >= startDay);
  const trend = p.trend.filter(t => t[0] >= startDay);
  const W = width, H = height, padL = 8, padR = 30, padT = 16, padB = 28;
  const innerW = W - padL - padR, innerH = H - padT - padB;
  const ys = [...hist.map(h => h[1]), ...trend.map(t => t[1])];
  const yMin = Math.min(...ys) - _SWING - 0.2, yMax = Math.max(...ys) + _SWING + 0.2;
  const xS = (d) => padL + ((d - startDay) / (FC.todayDay - startDay)) * innerW;
  const yS = (w) => padT + ((yMax - w) / (yMax - yMin)) * innerH;
  const trPts = trend.map(t => [xS(t[0]), yS(t[1])]);
  const bandTop = trend.map(t => [xS(t[0]), yS(t[1] + _SWING)]);
  const bandBot = trend.map(t => [xS(t[0]), yS(t[1] - _SWING)]).reverse();
  const bandPath = 'M ' + [...bandTop, ...bandBot].map(p => `${p[0].toFixed(1)} ${p[1].toFixed(1)}`).join(' L ') + ' Z';
  const today = hist[hist.length - 1], yest = hist[hist.length - 2];
  const tCol = 'var(--ink)';

  return (
    <svg width={W} height={H} viewBox={`0 0 ${W} ${H}`} style={{ display: 'block', overflow: 'visible', shapeRendering: 'geometricPrecision' }} role="img"
      aria-label={`Daily weigh-ins scattered within about plus or minus ${_SWING} kg of the trend.`}>
      {/* normal-range band */}
      <path d={bandPath} fill="var(--ink)" opacity="0.07" />
      {/* trend */}
      <path d={_cr2(trPts, 0.85)} fill="none" stroke={tCol} strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round" />
      {/* raw dots */}
      {hist.slice(0, -1).map(([d, w]) => <circle key={d} cx={xS(d)} cy={yS(w)} r="2.6" fill="var(--ink)" opacity="0.3" />)}
      {/* today dot + callout */}
      {today && (
        <g>
          <circle cx={xS(today[0])} cy={yS(today[1])} r="5" fill="var(--accent)" />
          <line x1={xS(today[0])} x2={xS(today[0])} y1={padT} y2={padT + innerH} stroke="var(--accent)" strokeWidth="0.6" opacity="0.4" />
        </g>
      )}
      {/* axis labels */}
      <g style={{ fontFeatureSettings: '"tnum"' }}>
        <text x={padL} y={padT + innerH + 17} fontFamily="var(--sans)" fontSize="10.5" fill="var(--ink-3)">2 weeks ago</text>
        <text x={xS(today[0])} y={padT + innerH + 17} textAnchor="end" fontFamily="var(--sans)" fontSize="10.5" fill="var(--ink-2)" fontWeight="600">Today</text>
      </g>
    </svg>
  );
}

function FCNoiseCard({ paceKey = 'onTrack', width = 360 }) {
  const p = window.computePace(paceKey);
  const hist = p.hist, today = hist[hist.length - 1][1], yest = hist[hist.length - 2][1];
  const dayDelta = today - yest;
  const up = dayDelta > 0.05;
  const weekly = Math.abs(p.weeklyVel);
  return (
    <div style={{ width: '100%' }}>
      <div style={{ fontFamily: 'var(--display)', fontSize: 10.5, letterSpacing: '0.18em', textTransform: 'uppercase', color: 'var(--ink-3)', fontWeight: 600 }}>Reading the trend</div>
      <div style={{ fontFamily: 'var(--sans)', fontSize: 20, fontWeight: 700, lineHeight: 1.22, letterSpacing: '-0.01em', color: 'var(--ink)', marginTop: 8, textWrap: 'balance' }}>
        {up ? `Up ${dayDelta.toFixed(1)} kg today. Still trending down.` : `A day up doesn’t mean off track.`}
      </div>
      <div style={{ display: 'flex', gap: 20, marginTop: 18, paddingTop: 16, borderTop: '1px solid var(--rule)' }}>
        <div style={{ flex: 1 }}>
          <div style={{ fontFamily: 'var(--sans)', fontSize: 13.5, fontWeight: 600, color: 'var(--ink-2)' }}>Daily swing</div>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 4, marginTop: 7 }}><span style={{ fontFamily: 'var(--num)', fontWeight: 300, fontSize: 30, color: 'var(--ink)', letterSpacing: '-0.02em' }}>±{_SWING.toFixed(1)}</span><span style={{ fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--ink-3)', fontWeight: 600 }}>kg</span></div>
        </div>
        <div style={{ flex: 1 }}>
          <div style={{ fontFamily: 'var(--sans)', fontSize: 13.5, fontWeight: 600, color: 'var(--ink-2)' }}>7-day trend</div>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 4, marginTop: 7 }}><span style={{ fontFamily: 'var(--num)', fontWeight: 300, fontSize: 30, color: 'var(--t-green)', letterSpacing: '-0.02em' }}>−{weekly.toFixed(1)}</span><span style={{ fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--ink-3)', fontWeight: 600 }}>kg/wk</span></div>
        </div>
      </div>
      <div style={{ marginTop: 16 }}><FCNoiseChart paceKey={paceKey} width={width} /></div>
    </div>
  );
}

Object.assign(window, { FCWaterCutChart, FCWaterCutCard, FCNoiseChart, FCNoiseCard });
