/* ============================================================
   timeline.jsx — bottom event timeline (exports window.Timeline)
   Per-sat rows with capture / downlink / prohibit / shadow bands,
   moving playhead, real-"now" marker, drag-to-scrub.
   ============================================================ */
const { useRef: useRefTL, useEffect: useEffectTL, useState: useStateTL } = React;

const TL_SPAN = 12 * 3600e3;     // visible window
const TL_LEAD = 0.32;            // playhead position fraction
const TL_GUTTER = 188;
const TL_ROW = 22;
const TL_AXIS = 26;

const TL_COL = {
  capture: "#d99a4e",
  downlink: "#5b9bd5",
  prohibit: "#d9685f",
  shadow: "rgba(120,140,180,0.30)",
};

function Timeline({ env, sched, simTime, domain, focusId, onScrub, onFocus, live }) {
  const wrapRef = useRefTL(null);
  const [w, setW] = useStateTL(1200);
  const dragRef = useRefTL(false);

  useEffectTL(() => {
    const ro = new ResizeObserver((es) => setW(es[0].contentRect.width));
    if (wrapRef.current) ro.observe(wrapRef.current);
    return () => ro.disconnect();
  }, []);

  const areaW = Math.max(200, w - TL_GUTTER);
  let viewStart = simTime - TL_LEAD * TL_SPAN;
  viewStart = Math.max(domain.start, Math.min(viewStart, domain.end - TL_SPAN));
  const viewEnd = viewStart + TL_SPAN;
  const X = (t) => TL_GUTTER + ((t - viewStart) / TL_SPAN) * areaW;
  const clampT = (t) => Math.max(viewStart, Math.min(viewEnd, t));

  const sats = env.sats;
  const rows = [];
  let y = TL_AXIS;
  let lastDomain = null;
  sats.forEach((s) => {
    if (s.domain !== lastDomain) { rows.push({ type: "group", label: s.domain, y }); y += 16; lastDomain = s.domain; }
    rows.push({ type: "sat", sat: s, y });
    y += TL_ROW;
  });
  const totalH = y + 6;

  // axis ticks (hourly)
  const ticks = [];
  const hour = 3600e3;
  let t0 = Math.ceil(viewStart / hour) * hour;
  for (let t = t0; t <= viewEnd; t += hour) ticks.push(t);

  function ptFromEvent(e) {
    const r = wrapRef.current.getBoundingClientRect();
    const x = e.clientX - r.left;
    const frac = (x - TL_GUTTER) / areaW;
    return viewStart + frac * TL_SPAN;
  }
  function down(e) {
    if (e.clientX - wrapRef.current.getBoundingClientRect().left < TL_GUTTER) return;
    dragRef.current = true; onScrub(ptFromEvent(e));
  }
  function move(e) { if (dragRef.current) onScrub(ptFromEvent(e)); }
  function up() { dragRef.current = false; }
  useEffectTL(() => {
    window.addEventListener("mousemove", move);
    window.addEventListener("mouseup", up);
    return () => { window.removeEventListener("mousemove", move); window.removeEventListener("mouseup", up); };
  });

  const nowX = X(Date.now());
  const headX = X(simTime);

  return (
    <div className="tl-wrap" ref={wrapRef} onMouseDown={down}>
      <svg width={w} height={totalH} style={{ display: "block" }}>
        <defs>
          <pattern id="hatch" width="6" height="6" patternTransform="rotate(45)" patternUnits="userSpaceOnUse">
            <rect width="6" height="6" fill="rgba(217,104,95,0.12)" />
            <line x1="0" y1="0" x2="0" y2="6" stroke="rgba(217,104,95,0.6)" strokeWidth="2" />
          </pattern>
        </defs>

        {/* axis */}
        <line x1={TL_GUTTER} y1={TL_AXIS} x2={w} y2={TL_AXIS} stroke="rgba(255,255,255,0.08)" />
        {ticks.map((t, i) => {
          const x = X(t); const d = new Date(t);
          const hh = String(d.getUTCHours()).padStart(2, "0");
          const isDay = d.getUTCHours() === 0;
          return (
            <g key={i}>
              <line x1={x} y1={TL_AXIS - 5} x2={x} y2={totalH} stroke="rgba(255,255,255,0.035)" />
              <text x={x + 3} y={TL_AXIS - 9} className="tl-tick">
                {isDay ? `${String(d.getUTCDate()).padStart(2, "0")}.${String(d.getUTCMonth() + 1).padStart(2, "0")}` : `${hh}:00`}
              </text>
            </g>
          );
        })}

        {/* rows */}
        {rows.map((r, i) => {
          if (r.type === "group") {
            return <text key={i} x={10} y={r.y + 11} className="tl-group">{r.label}</text>;
          }
          const s = r.sat;
          const tr = sched[s.id] || {};
          const dim = focusId && focusId !== s.id;
          const cy = r.y + TL_ROW / 2;
          const band = (iv, key, fill, h) => {
            const x1 = X(Math.max(iv.start, viewStart)), x2 = X(Math.min(iv.end, viewEnd));
            if (x2 <= TL_GUTTER || x1 >= w || x2 - x1 < 0.6) return null;
            return <rect key={key} x={x1} y={cy - h / 2} width={Math.max(1.5, x2 - x1)} height={h}
              fill={fill} rx="1" opacity={dim ? 0.3 : 1} />;
          };
          return (
            <g key={i} onClick={() => onFocus(focusId === s.id ? null : s.id)} style={{ cursor: "pointer" }}>
              <rect x={0} y={r.y} width={w} height={TL_ROW} fill={focusId === s.id ? "rgba(95,179,163,0.06)" : "transparent"} />
              <line x1={TL_GUTTER} y1={r.y + TL_ROW} x2={w} y2={r.y + TL_ROW} stroke="rgba(255,255,255,0.025)" />
              <circle cx={14} cy={cy} r={3} fill={s.color} opacity={dim ? 0.4 : 1} />
              <text x={24} y={cy + 3.5} className="tl-name" opacity={dim ? 0.45 : 1}>{s.name}</text>
              {/* baseline */}
              <line x1={TL_GUTTER} y1={cy} x2={w} y2={cy} stroke="rgba(255,255,255,0.04)" />
              {/* shadow (under) */}
              {(tr.shadow || []).map((iv, k) => band(iv, "sh" + k, TL_COL.shadow, TL_ROW - 8))}
              {/* downlink */}
              {(tr.downlink || []).map((iv, k) => band(iv, "dl" + k, TL_COL.downlink, 8))}
              {/* capture */}
              {(tr.capture || []).map((iv, k) => band(iv, "cp" + k, TL_COL.capture, 10))}
              {/* prohibit (hatched, full height) */}
              {(tr.prohibit || []).map((iv, k) => {
                const x1 = X(Math.max(iv.start, viewStart)), x2 = X(Math.min(iv.end, viewEnd));
                if (x2 <= TL_GUTTER || x1 >= w || x2 - x1 < 0.6) return null;
                return <rect key={"pr" + k} x={x1} y={r.y + 2} width={Math.max(2, x2 - x1)} height={TL_ROW - 4}
                  fill="url(#hatch)" stroke="rgba(217,104,95,0.5)" strokeWidth="0.8" opacity={dim ? 0.4 : 1} />;
              })}
            </g>
          );
        })}

        {/* now marker (real wall clock) */}
        {nowX > TL_GUTTER && nowX < w && (
          <g>
            <line x1={nowX} y1={TL_AXIS - 5} x2={nowX} y2={totalH} stroke="rgba(95,179,163,0.35)" strokeDasharray="2 3" />
            <text x={nowX + 3} y={totalH - 3} className="tl-nowlbl">СЕЙЧАС</text>
          </g>
        )}
        {/* playhead */}
        <g>
          <line x1={headX} y1={TL_AXIS - 6} x2={headX} y2={totalH} stroke={live ? "#5fb3a3" : "#d99a4e"} strokeWidth="1.5" />
          <polygon points={`${headX - 5},${TL_AXIS - 6} ${headX + 5},${TL_AXIS - 6} ${headX},${TL_AXIS + 1}`} fill={live ? "#5fb3a3" : "#d99a4e"} />
        </g>
      </svg>
    </div>
  );
}

window.Timeline = Timeline;
