// Timeline row + tooltip + inline mini-player.

const { useState: useStateT, useEffect: useEffectT, useRef: useRefT, useMemo: useMemoT, useCallback: useCallbackT } = React;

// ----- Tooltip (single, portal-style fixed positioning) -----

function Tooltip({ data }) {
  if (!data) return null;
  const { meow, row, x, y } = data;
  const startDate = MeowUtil.fracToDate(meow.start, row.startDate);
  const endDate = MeowUtil.fracToDate(meow.end, row.startDate);
  const W = 232;
  // html has CSS `zoom`, which scales fixed-positioned descendants. clientX/Y
  // come back in unscaled viewport pixels, so divide to match the local
  // coordinate space the browser uses when laying out left/top.
  const z = parseFloat(getComputedStyle(document.documentElement).zoom) || 1;
  const cx = x / z;
  const cy = y / z;
  const vw = window.innerWidth / z;
  const vh = window.innerHeight / z;
  let left = cx + 14;
  let top = cy + 14;
  if (left + W > vw - 8) left = cx - W - 14;
  if (top + 160 > vh - 8) top = cy - 160;

  return (
    <div className="tooltip" style={{ left, top, '--score-color': MeowUtil.scoreColor(meow.score) }}>
      <div className="tt-header">
        <span className={'tt-dot tt-dot-' + meow.label.toLowerCase()} />
        <span className="tt-label">{meow.label}</span>
        <span className="tt-score" style={{ color: MeowUtil.scoreColor(meow.score) }}>
          {meow.score.toFixed(2)}
        </span>
      </div>
      <div className="tt-row">
        <span className="tt-k">start</span>
        <span className="tt-v tt-mono">{MeowUtil.fmtClock(startDate)}</span>
      </div>
      <div className="tt-row">
        <span className="tt-k">end</span>
        <span className="tt-v tt-mono">{MeowUtil.fmtClock(endDate)}</span>
      </div>
      <div className="tt-row">
        <span className="tt-k">duration</span>
        <span className="tt-v tt-mono">{meow.durSec.toFixed(1)}s</span>
      </div>
      <div className="tt-row">
        <span className="tt-k">date</span>
        <span className="tt-v">{MeowUtil.fmtDayLabel(startDate)}</span>
      </div>
      <div className="tt-bar">
        <div className="tt-bar-fill" style={{ width: (meow.score * 100) + '%', background: MeowUtil.scoreColor(meow.score) }} />
      </div>
      <div className="tt-hint">click to play</div>
    </div>
  );
}

// ----- Inline mini-player -----

function MiniPlayer({ player, onClose, rowRect }) {
  const [progress, setProgress] = useStateT(0);
  const startedRef = useRefT(0);
  const rafRef = useRefT(0);

  useEffectT(() => {
    startedRef.current = performance.now();
    function tick() {
      const elapsed = (performance.now() - startedRef.current) / 1000;
      const p = Math.min(1, elapsed / player.dur);
      setProgress(p);
      if (p < 1) rafRef.current = requestAnimationFrame(tick);
    }
    rafRef.current = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(rafRef.current);
  }, [player.dur]);

  const meow = player.meow;

  return (
    <div className="mini-player" style={{ left: player.x, top: player.y, '--score-color': MeowUtil.scoreColor(meow.score) }}>
      <button className="mp-play" onClick={() => { /* already playing */ }} aria-label="Playing">
        <span className="mp-play-pulse" />
        <svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor"><polygon points="6 4 20 12 6 20" /></svg>
      </button>
      <div className="mp-body">
        <div className="mp-meta">
          <span className="mp-label">{meow.label}</span>
          <span className="mp-time tt-mono">{MeowUtil.fmtClock(MeowUtil.fracToDate(meow.start, player.row.startDate))}</span>
          <span className="mp-score" style={{ color: MeowUtil.scoreColor(meow.score) }}>{meow.score.toFixed(2)}</span>
        </div>
        <div className="mp-bar">
          <div className="mp-bar-fill" style={{ width: (progress * 100) + '%' }} />
        </div>
      </div>
      <button className="mp-close" onClick={onClose} aria-label="Close">
        <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round"><line x1="6" y1="6" x2="18" y2="18" /><line x1="18" y1="6" x2="6" y2="18" /></svg>
      </button>
    </div>
  );
}

// ----- Single row -----

function TimelineRow(props) {
  const {
    row, zoom, pan, scoreThreshold, enabledLabels,
    isToday, onBlockHover, onBlockLeave, onBlockClick,
    activeMeowId,
  } = props;

  const filtered = useMemoT(() => {
    return row.meows.filter((m) => m.score >= scoreThreshold && enabledLabels.has(m.label));
  }, [row.meows, scoreThreshold, enabledLabels]);

  // Min visible width so 2-second meows are still clickable.
  const MIN_PX = 3;

  return (
    <div className={'row ' + (isToday ? 'row-today' : '')}>
      <div className="row-header">
        <div className="row-date">
          <span className="row-dow">{MeowUtil.fmtDayRangeLabel(row.startDate).split(' ')[0]}</span>
          <span className="row-md">{MeowUtil.fmtDayRangeLabel(row.startDate).split(' ').slice(1).join(' ')}</span>
        </div>
        <div className="row-count" title={`${filtered.length} of ${row.meows.length} meows`}>
          <span className="row-count-num">{filtered.length}</span>
        </div>
      </div>
      <div className="row-track-outer">
        <div
          className="row-track"
          style={{
            width: (zoom * 100) + '%',
            transform: `translateX(${-pan}px)`,
          }}
        >
          {/* No-recording overlay — darkens any portion outside recording periods */}
          <div className="row-norec">
            {(() => {
              const periods = (row.periods || []).slice().sort((a, b) => a.start - b.start);
              const gaps = [];
              let cursor = 0;
              for (const p of periods) {
                if (p.start > cursor) gaps.push({ start: cursor, end: p.start });
                cursor = Math.max(cursor, p.end);
              }
              if (cursor < 1) gaps.push({ start: cursor, end: 1 });
              return gaps.map((g, i) => (
                <div
                  key={i}
                  className="norec-band"
                  style={{
                    left: (g.start * 100) + '%',
                    width: ((g.end - g.start) * 100) + '%',
                  }}
                  title="No recording"
                />
              ));
            })()}
          </div>

          {/* Hour ticks */}
          <div className="row-ticks">
            {MeowUtil.HOUR_TICKS.map((t, i) => (
              <div
                key={i}
                className={'tick ' + (t.labeled ? 'tick-major' : 'tick-minor')}
                style={{ left: (t.frac * 100) + '%' }}
              />
            ))}
          </div>

          {/* Meow blocks */}
          <div className="row-blocks">
            {filtered.map((m) => {
              const leftPct = m.start * 100;
              const widthPct = Math.max(0, (m.end - m.start) * 100);
              // We boost min width via min-width css to keep blocks clickable
              const isActive = activeMeowId === m.id;
              return (
                <div
                  key={m.id}
                  className={'block ' + (isActive ? 'block-active' : '')}
                  data-label={m.label.toLowerCase()}
                  style={{
                    left: leftPct + '%',
                    width: widthPct + '%',
                    minWidth: MIN_PX + 'px',
                    background: MeowUtil.scoreColor(m.score),
                    '--score-color': MeowUtil.scoreColor(m.score),
                    '--score': m.score,
                  }}
                  onMouseEnter={(e) => onBlockHover(m, row, e)}
                  onMouseMove={(e) => onBlockHover(m, row, e)}
                  onMouseLeave={() => onBlockLeave()}
                  onClick={(e) => { e.stopPropagation(); onBlockClick(m, row, e); }}
                />
              );
            })}
          </div>
        </div>
      </div>
    </div>
  );
}

window.TimelineRow = TimelineRow;
window.Tooltip = Tooltip;
window.MiniPlayer = MiniPlayer;
