// 共用 · 今天视图 —— 以「现在」为中心的呼吸景深 + 底部今天小河
const { useState, useEffect, useRef, useCallback } = React;

function catColor(id) { return (window.CATS[id] || {}).color || '#9DB4BF'; }
function catName(id) { return (window.CATS[id] || {}).name || ''; }

// 底部「今天小河」缩影：一眼扫全天节奏，可点、可拖着划过全天
function RiverMini({ moments, focus, onPick }) {
  const W = 360, H = 64;
  const wrapRef = useRef(null);
  const dragging = useRef(false);
  const wave = `M0 ${H*0.55} C ${W*0.2} ${H*0.30}, ${W*0.32} ${H*0.78}, ${W*0.5} ${H*0.52}
                S ${W*0.8} ${H*0.30}, ${W} ${H*0.5}`;
  const xOf = (min) => 14 + (min / 1440) * (W - 28);
  const yOf = 0.5 * H;
  const nowMin = moments[focus] ? moments[focus].min : 0;

  // 拖动 = 在全天里"划"过去：按手指位置取最近的时刻
  const pickFromX = (clientX) => {
    const el = wrapRef.current; if (!el) return;
    const r = el.getBoundingClientRect();
    const pad = 14 / W;
    const frac = Math.max(0, Math.min(1, ((clientX - r.left) / r.width - pad) / (1 - 2 * pad)));
    let best = -1, bestD = Infinity;
    moments.forEach((m, i) => {
      if (m.kind === 'spine') return;
      const d = Math.abs(m.min / 1440 - frac);
      if (d < bestD) { bestD = d; best = i; }
    });
    if (best >= 0 && best !== focus) onPick(best);
  };
  const onDown = (e) => { dragging.current = true; try { e.currentTarget.setPointerCapture(e.pointerId); } catch (_) {} pickFromX(e.clientX); };
  const onMove = (e) => { if (dragging.current) pickFromX(e.clientX); };
  const onUp = () => { dragging.current = false; };

  return (
    <div ref={wrapRef} style={tStyles.riverWrap}
      onPointerDown={onDown} onPointerMove={onMove} onPointerUp={onUp} onPointerCancel={onUp}>
      <svg viewBox={`0 0 ${W} ${H}`} width="100%" height={H} preserveAspectRatio="none" style={{ overflow: 'visible', display: 'block', pointerEvents: 'none' }}>
        <defs>
          <linearGradient id="rmFlow" x1="0" y1="0" x2="1" y2="0">
            <stop offset="0%" stopColor="#BFE9DA" /><stop offset="50%" stopColor="#BBD8FF" /><stop offset="100%" stopColor="#FFD0E6" />
          </linearGradient>
          <filter id="rmGlow"><feGaussianBlur stdDeviation="2.4" /></filter>
        </defs>
        <path d={wave} fill="none" stroke="url(#rmFlow)" strokeWidth="9" strokeLinecap="round" opacity="0.85" />
        <path d={wave} fill="none" stroke="#fff" strokeWidth="2" strokeLinecap="round" opacity="0.5">
          <animate attributeName="stroke-dashoffset" from="60" to="0" dur="3s" repeatCount="indefinite" />
        </path>
        {moments.map((m, i) => {
          if (m.kind === 'spine') return null;
          const x = xOf(m.min);
          return (
            <g key={i}>
              <circle cx={x} cy={yOf} r={i === focus ? 7 : 4.5} fill={catColor(m.cat)}
                opacity={m.done ? 0.4 : 0.95} />
              {i === focus && <circle cx={x} cy={yOf} r="11" fill="none" stroke={catColor(m.cat)} strokeWidth="1.6" opacity="0.5" />}
            </g>
          );
        })}
        {/* 当下水滴 */}
        <g filter="url(#rmGlow)">
          <circle cx={xOf(nowMin)} cy={yOf} r="5.5" fill="#fff" opacity="0.9" />
        </g>
      </svg>
      <div style={tStyles.riverTicks}>
        <span>晨</span><span>午</span><span>傍晚</span><span>夜</span>
      </div>
    </div>
  );
}

function TodayView({ dayNum, embedded }) {
  const day = window.MONTH[dayNum - 1];
  const moments = React.useMemo(() => window.buildDay(dayNum), [dayNum]);
  const defaultFocus = Math.max(0, moments.findIndex(m => m.now));
  const [focus, setFocus] = useState(defaultFocus < 0 ? 0 : defaultFocus);
  const wrapRef = useRef(null);
  const accum = useRef(0);

  useEffect(() => { setFocus(defaultFocus < 0 ? 0 : defaultFocus); }, [dayNum]);

  // 滚动 = 穿过时间
  useEffect(() => {
    const el = wrapRef.current; if (!el) return;
    const onWheel = (e) => {
      e.preventDefault();
      accum.current += e.deltaY;
      if (Math.abs(accum.current) > 42) {
        setFocus(f => Math.min(moments.length - 1, Math.max(0, f + (accum.current > 0 ? 1 : -1))));
        accum.current = 0;
      }
    };
    el.addEventListener('wheel', onWheel, { passive: false });
    // 触摸
    let startY = 0;
    const onTS = (e) => { startY = e.touches[0].clientY; };
    const onTM = (e) => {
      const dy = startY - e.touches[0].clientY;
      if (Math.abs(dy) > 40) {
        setFocus(f => Math.min(moments.length - 1, Math.max(0, f + (dy > 0 ? 1 : -1))));
        startY = e.touches[0].clientY;
        e.preventDefault();
      }
    };
    el.addEventListener('touchstart', onTS, { passive: true });
    el.addEventListener('touchmove', onTM, { passive: false });
    return () => { el.removeEventListener('wheel', onWheel); el.removeEventListener('touchstart', onTS); el.removeEventListener('touchmove', onTM); };
  }, [moments.length]);

  const ch = window.CHANNELS[day.channel];

  return (
    <div style={tStyles.root}>
      {!embedded && (
        <div style={tStyles.head}>
          <div style={tStyles.dateBig}>{dayNum}<span style={tStyles.dateSmall}> 周{day.weekday}</span></div>
          <div style={{ ...tStyles.chTag, background: ch.tint }}>
            <span style={{ ...tStyles.chDot, background: ch.glow }} />{ch.name}日 · {ch.sub}
          </div>
        </div>
      )}

      {/* 呼吸景深栈 */}
      <div ref={wrapRef} style={tStyles.depthWrap}>
        <div style={tStyles.depthStage}>
          {moments.map((m, i) => {
            const dist = i - focus;
            const ad = Math.abs(dist);
            const scale = Math.max(0.62, 1 - ad * 0.13);
            const ty = dist * 92 - Math.sign(dist) * Math.min(ad, 1) * 6;
            const blur = ad === 0 ? 0 : Math.min(5, ad * 1.6);
            const opacity = ad === 0 ? 1 : Math.max(0.18, 0.8 - ad * 0.22);
            const z = 100 - ad;
            const isNow = i === focus;
            const spine = m.kind === 'spine';
            return (
              <div key={i}
                onClick={() => setFocus(i)}
                style={{
                  ...tStyles.moment,
                  transform: `translate(-50%, -50%) translateY(${ty}px) scale(${scale})`,
                  filter: `blur(${blur}px)`,
                  opacity,
                  zIndex: z,
                  width: spine ? '62%' : '80%',
                }}>
                {spine ? (
                  <div style={{ ...tStyles.spineCard, ...(isNow ? tStyles.spineNow : {}) }}>
                    <span style={tStyles.spineTime}>{m.time}</span>
                    <span style={tStyles.spineTitle}>{m.title}</span>
                  </div>
                ) : (
                  <div style={{
                    ...tStyles.card,
                    ...(isNow ? tStyles.cardNow : {}),
                    ...(m.done ? tStyles.cardDone : {}),
                    boxShadow: isNow ? `0 24px 60px -16px ${catColor(m.cat)}88, 0 0 0 1px rgba(255,255,255,.7) inset` : tStyles.card.boxShadow,
                  }}>
                    {isNow && dayNum === window.TODAY && <div style={tStyles.nowLabel}>此刻</div>}
                    <div style={tStyles.cardTop}>
                      <span style={tStyles.cardTime}>{m.time}</span>
                      <span style={{ ...tStyles.cardCat, color: catColor(m.cat) }}>
                        <span style={{ ...tStyles.catDot, background: catColor(m.cat) }} />{catName(m.cat)}
                        {m.kind === 'event' && <span style={tStyles.eventPin}>· 约定</span>}
                      </span>
                    </div>
                    <div style={{ ...tStyles.cardTitle, fontSize: isNow ? 27 : 20 }}>{m.title}</div>
                    {isNow && dayNum === window.TODAY && <div style={tStyles.cardHint}>{ch.name}日 · 顺着节奏来，不急</div>}
                    {m.done && <div style={tStyles.doneMark}>已完成</div>}
                  </div>
                )}
              </div>
            );
          })}
        </div>
      </div>

      {/* 底部今天小河 */}
      <RiverMini moments={moments} focus={focus} onPick={setFocus} />
    </div>
  );
}

const tStyles = {
  root: { flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' },
  head: { padding: '18px 24px 4px', display: 'flex', alignItems: 'baseline', justifyContent: 'space-between' },
  dateBig: { fontSize: 34, fontWeight: 700, color: 'var(--ink)', letterSpacing: '-0.5px' },
  dateSmall: { fontSize: 16, fontWeight: 600, color: 'var(--ink-soft)' },
  chTag: { fontSize: 13, fontWeight: 600, color: 'var(--ink)', padding: '6px 12px', borderRadius: 999, display: 'flex', alignItems: 'center', gap: 6, boxShadow: '0 4px 14px -6px rgba(54,84,99,.3)' },
  chDot: { width: 8, height: 8, borderRadius: 999, display: 'inline-block' },

  depthWrap: { flex: 1, minHeight: 0, position: 'relative', overflow: 'hidden', touchAction: 'none' },
  depthStage: { position: 'absolute', inset: 0 },
  moment: { position: 'absolute', left: '50%', top: '50%', transition: 'transform .5s cubic-bezier(.22,.9,.3,1), opacity .5s ease, filter .5s ease', willChange: 'transform' },

  card: { background: 'var(--glass-strong)', borderRadius: 26, padding: '16px 20px', border: '1px solid var(--stroke)', boxShadow: '0 14px 36px -18px rgba(54,84,99,.4)', backdropFilter: 'blur(8px)', cursor: 'pointer' },
  cardNow: { background: 'rgba(255,255,255,0.9)', padding: '22px 24px' },
  cardDone: { background: 'rgba(255,255,255,0.42)' },
  cardTop: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 },
  cardTime: { fontSize: 13, fontWeight: 600, color: 'var(--ink-soft)' },
  cardCat: { fontSize: 12, fontWeight: 600, display: 'flex', alignItems: 'center', gap: 5 },
  catDot: { width: 7, height: 7, borderRadius: 999, display: 'inline-block' },
  eventPin: { color: 'var(--ink-faint)', marginLeft: 2 },
  cardTitle: { fontWeight: 700, color: 'var(--ink)', lineHeight: 1.25, letterSpacing: '-0.3px' },
  cardHint: { marginTop: 8, fontSize: 13, color: 'var(--ink-soft)' },
  nowLabel: { position: 'absolute', top: -11, left: 22, background: 'linear-gradient(120deg,#6FCBB2,#6FB4FF)', color: '#fff', fontSize: 11, fontWeight: 700, padding: '3px 10px', borderRadius: 999, letterSpacing: '1px', boxShadow: '0 6px 14px -4px rgba(111,180,178,.6)' },
  doneMark: { position: 'absolute', top: 14, right: 16, fontSize: 11, fontWeight: 600, color: 'var(--ink-faint)' },

  spineCard: { display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 10, padding: '9px 16px', borderRadius: 999, background: 'rgba(255,255,255,0.4)', border: '1px dashed rgba(110,140,155,.35)' },
  spineNow: { background: 'rgba(255,255,255,0.7)', borderStyle: 'solid' },
  spineTime: { fontSize: 12, fontWeight: 600, color: 'var(--ink-faint)' },
  spineTitle: { fontSize: 14, fontWeight: 600, color: 'var(--ink-soft)' },

  riverWrap: { padding: '6px 14px 12px', flexShrink: 0, touchAction: 'none', cursor: 'grab', userSelect: 'none', WebkitUserSelect: 'none' },
  riverTicks: { display: 'flex', justifyContent: 'space-between', padding: '2px 18px 0', fontSize: 11, color: 'var(--ink-faint)', fontWeight: 600 },
};

window.TodayView = TodayView;
