// Click-to-stamp lyric timing for the side panel. The panel has no audio of its own,
// so a stopwatch the user starts is the clock (the recording plays in any tab/app) —
// mirroring the desktop app's "click each line as it's sung". Reuses the shared
// TimingSession; saves keyed by song. Kept as its own module so it can be driven in a
// test harness (tests/panel-timing-demo.html) without loading the whole panel.
import { TimingSession, saveContribution } from "./author.js";
import { esc } from "./util.js";

function fmtClock(s) {
  if (!Number.isFinite(s)) return "—";
  const m = Math.floor(s / 60), r = s - m * 60;
  return m + ":" + (r < 10 ? "0" : "") + r.toFixed(1);
}

// Mount the tool into `slot`. `groups` = [{i, es, en}] (i = original es-line index),
// `prior` = a restored session shape or null, `onDone` = called when the user exits.
// Returns { teardown } to stop the clock + key handler on navigation.
export function mountPanelTiming({ slot, song, groups, prior, onDone }) {
  const session = new TimingSession(groups.length, prior);
  const clock = { running: false, accum: 0, base: 0 };
  const now = () => performance.now();
  const elapsed = () => clock.accum + (clock.running ? (now() - clock.base) / 1000 : 0);

  slot.innerHTML = `<div class="section-h">Timing — ${esc(song.t)}
      <button class="time-btn" id="pt-done">Done</button></div>
    <div class="ptiming">
      <div class="pt-bar">
        <button class="pt-play" id="pt-toggle">▶ Start</button>
        <span class="pt-clock" id="pt-clock">0:00.0</span>
        <button class="pt-mini" id="pt-reset">Reset</button>
        <span class="pt-prog" id="pt-prog"></span>
      </div>
      <div class="pt-anchors">
        <button class="pt-mini" id="pt-start">Mark start</button><span class="pt-chip" id="pt-startc">—</span>
        <button class="pt-mini" id="pt-end">Mark end</button><span class="pt-chip" id="pt-endc">—</span>
      </div>
      <div class="pt-tip">Play the recording (any tab or app), press <b>Start</b>, then click each line —
        or press <b>Space</b> — as it’s sung. <b>⌫</b> undoes; tap a line again to re-stamp.</div>
      <ol class="pt-lines" id="pt-lines">${groups.map((g, pos) =>
        `<li class="pt-ln" data-pos="${pos}"><span class="pt-t"></span>
           <span class="pt-x"><span class="es">${esc(g.es)}</span>${g.en ? `<span class="en">${esc(g.en)}</span>` : ""}</span></li>`).join("")}</ol>
      <div class="pt-saved" id="pt-saved" hidden></div>
      <div class="pt-foot">
        <button class="pt-tap" id="pt-tap">TAP the next line ⌴</button>
        <button class="pt-mini" id="pt-undo">↺ Undo</button>
        <button class="btn" id="pt-save">✓ Save</button>
      </div></div>`;

  const $ = (id) => slot.querySelector("#" + id);
  const linesEl = $("pt-lines");
  const refresh = () => {
    linesEl.querySelectorAll(".pt-ln").forEach((el) => {
      const pos = +el.dataset.pos, t = session.times[pos];
      el.classList.toggle("done", t != null);
      el.classList.toggle("cur", pos === session.cursor);
      el.querySelector(".pt-t").textContent = t != null ? fmtClock(t) : (pos === session.cursor ? "▸" : "");
    });
    $("pt-prog").textContent = session.stampedCount() + "/" + session.n;
    $("pt-startc").textContent = session.start != null ? fmtClock(session.start) : "—";
    $("pt-endc").textContent = session.end != null ? fmtClock(session.end) : "—";
    const cur = linesEl.querySelector(".pt-ln.cur");
    if (cur) {
      const top = linesEl.scrollTop + (cur.getBoundingClientRect().top - linesEl.getBoundingClientRect().top) - linesEl.clientHeight / 2;
      linesEl.scrollTop = Math.max(0, top);
    }
  };
  const tick = () => { $("pt-clock").textContent = fmtClock(elapsed()); };
  const clockTimer = setInterval(tick, 100);

  const startClock = () => { clock.base = now(); clock.running = true; $("pt-toggle").textContent = "⏸ Pause"; };
  // Auto-start on the first stamp so a forgotten "Start" can't make every time 0.
  const ensureRunning = () => { if (!clock.running) startClock(); };
  $("pt-toggle").addEventListener("click", () => {
    if (clock.running) { clock.accum = elapsed(); clock.running = false; $("pt-toggle").textContent = "▶ Resume"; }
    else startClock();
  });
  $("pt-reset").addEventListener("click", () => {
    clock.accum = 0; clock.running = false; clock.base = now(); $("pt-toggle").textContent = "▶ Start"; tick();
  });
  const stamp = () => { ensureRunning(); session.stampNext(elapsed()); refresh(); };
  $("pt-tap").addEventListener("click", stamp);
  $("pt-undo").addEventListener("click", () => { session.undo(); refresh(); });
  $("pt-start").addEventListener("click", () => { ensureRunning(); session.markStart(elapsed()); refresh(); });
  $("pt-end").addEventListener("click", () => { session.markEnd(elapsed()); refresh(); });
  linesEl.querySelectorAll(".pt-ln").forEach((el) =>
    el.addEventListener("click", () => { ensureRunning(); session.stampLine(+el.dataset.pos, elapsed()); refresh(); }));
  $("pt-save").addEventListener("click", async () => {
    const c = session.build({ song, lineText: groups.map((g) => g.es), source: "panel" });
    // session indexes by GROUP position; store the ORIGINAL es-line index for folding.
    c.lines = c.lines.map((l) => ({ i: groups[l.i] ? groups[l.i].i : l.i, text: l.text, t: l.t }));
    const ok = await saveContribution(c);
    const sv = $("pt-saved"); sv.hidden = false;
    sv.textContent = ok
      ? `Saved ✓ ${c.lines.length} lines · start ${fmtClock(c.startSec)} · end ${fmtClock(c.endSec)}`
      : "Couldn’t save (storage unavailable).";
  });

  const onKey = (e) => {
    if (e.code === "Space") { e.preventDefault(); stamp(); }
    else if (e.code === "Backspace") { e.preventDefault(); session.undo(); refresh(); }
  };
  document.addEventListener("keydown", onKey, true);

  const teardown = () => {
    clearInterval(clockTimer);
    document.removeEventListener("keydown", onKey, true);
  };
  $("pt-done").addEventListener("click", () => { teardown(); if (onDone) onDone(); });

  refresh();
  return { teardown };
}
