(function () {
  const root = document.getElementById("regia-app");
  if (!root) return;

  const cfg = {
    token: root.dataset.token,
    statusUrl: root.dataset.statusUrl,
    scoreUrl: root.dataset.scoreUrl,
    pauseUrl: root.dataset.pauseUrl,
    stopUrl: root.dataset.stopUrl,
    cableUrl: root.dataset.cableUrl,
    hlsUrl: root.dataset.hlsUrl,
    homeName: root.dataset.homeName,
    awayName: root.dataset.awayName,
    shareUrl: root.dataset.shareUrl,
    shareTitle: root.dataset.shareTitle,
    streamClosed: root.dataset.streamClosed === "true"
  };

  const els = {
    badge: document.getElementById("regia-badge"),
    setsLine: document.getElementById("sets-line"),
    scoreLine: document.getElementById("score-line"),
    partialsLine: document.getElementById("partials-line"),
    homePoints: document.getElementById("home-points"),
    toast: document.getElementById("regia-toast"),
    modal: document.getElementById("regia-modal"),
    modalTitle: document.getElementById("modal-title"),
    modalBody: document.getElementById("modal-body"),
    modalConfirm: document.getElementById("modal-confirm"),
    modalCancel: document.getElementById("modal-cancel"),
    preview: document.getElementById("regia-preview"),
    previewPlaceholder: document.getElementById("regia-preview-placeholder")
  };

  let pendingAction = null;
  let hls = null;
  let previewStarted = false;

  function toast(msg) {
    els.toast.textContent = msg;
    els.toast.classList.add("visible");
    setTimeout(() => els.toast.classList.remove("visible"), 2800);
  }

  function formatPartials(partials) {
    if (!partials || !partials.length) return "";
    return partials
      .map((p) => `Set ${p.set || p["set"]} ${p.home || p["home"]}-${p.away || p["away"]}`)
      .join(" · ");
  }

  function applyScorePayload(data) {
    const s = data.score;
    if (!s) return;

    const homePts = s.home_points ?? s.homePoints;
    const awayPts = s.away_points ?? s.awayPoints;
    const homeSets = s.home_sets ?? s.homeSets;
    const awaySets = s.away_sets ?? s.awaySets;
    const currentSet = s.current_set ?? s.currentSet;

    const awayEl = document.getElementById("away-points");
    els.homePoints.textContent = homePts;
    if (awayEl) awayEl.textContent = awayPts;
    els.setsLine.textContent = `Set ${currentSet} · Set vinti ${homeSets}-${awaySets}`;
    els.scoreLine.textContent = `${cfg.homeName} ${homePts} - ${awayPts} ${cfg.awayName}`;

    const partialsText = formatPartials(s.set_partials || s.setPartials);
    if (partialsText) {
      els.partialsLine.textContent = `Parziali: ${partialsText}`;
      els.partialsLine.hidden = false;
    }
  }

  function setBadge(data) {
    if (data.stream_closed) {
      els.badge.textContent = "Terminata";
      els.badge.className = "regia-badge regia-badge--ended";
      return;
    }
    if (data.on_air) {
      els.badge.textContent = "In onda";
      els.badge.className = "regia-badge regia-badge--live";
    } else {
      els.badge.textContent = "In attesa";
      els.badge.className = "regia-badge regia-badge--wait";
    }
  }

  async function postScore(action) {
    const res = await fetch(cfg.scoreUrl, {
      method: "PATCH",
      headers: { "Content-Type": "application/json", Accept: "application/json" },
      body: JSON.stringify({ cmd: action })
    });
    if (!res.ok) throw new Error("Errore aggiornamento punteggio");
    return res.json();
  }

  async function handleAction(action) {
    try {
      const data = await postScore(action);
      applyScorePayload(data);
      setBadge(data);

      if (data.set_won && action !== "close_set") {
        const winner = data.winner === "home" ? cfg.homeName : cfg.awayName;
        openModal("Set vinto", `${winner} ha vinto il set. Chiudere il set?`, () => postScore("close_set"));
      } else if (data.match_won) {
        const winner = data.winner === "home" ? cfg.homeName : cfg.awayName;
        openModal("Partita vinta", `${winner} ha vinto la partita. Chiudere la diretta?`, () => stopStream());
      }
    } catch (e) {
      toast(e.message || "Errore");
    }
  }

  function openModal(title, body, onConfirm) {
    els.modalTitle.textContent = title;
    els.modalBody.textContent = body;
    els.modal.classList.add("open");
    pendingAction = onConfirm;
  }

  function closeModal() {
    els.modal.classList.remove("open");
    pendingAction = null;
  }

  els.modalConfirm.addEventListener("click", async () => {
    const fn = pendingAction;
    closeModal();
    if (fn) {
      try {
        const data = await fn();
        if (data) {
          applyScorePayload(data);
          setBadge(data);
        }
      } catch (e) {
        toast(e.message || "Errore");
      }
    }
  });

  els.modalCancel.addEventListener("click", closeModal);

  root.querySelectorAll("[data-action]").forEach((btn) => {
    btn.addEventListener("click", () => {
      const action = btn.dataset.action;
      if (action === "close_set") {
        openModal("Chiudi set", "Confermi la chiusura del set corrente?", () => postScore("close_set"));
      } else {
        handleAction(action);
      }
    });
  });

  function syncPreviewFromStatus(data) {
    if (data.stream_closed) {
      cfg.streamClosed = true;
      stopPreview();
      return;
    }

    if (data.on_air) {
      if (!previewStarted) startPreview();
      else if (els.preview && els.preview.readyState >= 2) hidePreviewPlaceholder();
    } else {
      destroyPreview();
      showPreviewPlaceholder("Anteprima in attesa del segnale…");
    }
  }

  async function pollStatus() {
    try {
      const res = await fetch(cfg.statusUrl, { headers: { Accept: "application/json" } });
      if (!res.ok) return;
      const data = await res.json();
      applyScorePayload(data);
      setBadge(data);
      syncPreviewFromStatus(data);
    } catch (_) {}
  }

  function bindPreviewEvents() {
    if (!els.preview) return;
    ["playing", "loadeddata", "canplay"].forEach((ev) => {
      els.preview.addEventListener(ev, hidePreviewPlaceholder);
    });
  }

  function startPreview() {
    if (cfg.streamClosed || !els.preview || !cfg.hlsUrl || previewStarted) return;

    previewStarted = true;
    const url = hlsUrlFresh();

    if (window.Hls && Hls.isSupported()) {
      hls = new Hls({ lowLatencyMode: true, maxBufferLength: 8 });
      hls.loadSource(url);
      hls.attachMedia(els.preview);
      hls.on(Hls.Events.MANIFEST_PARSED, () => {
        els.preview.play().catch(() => {});
      });
      hls.on(Hls.Events.ERROR, (_, err) => {
        if (err.fatal) {
          destroyPreview();
          setTimeout(() => {
            if (!cfg.streamClosed) startPreview();
          }, 2500);
        }
      });
    } else if (els.preview.canPlayType("application/vnd.apple.mpegurl")) {
      els.preview.src = url;
      els.preview.addEventListener(
        "loadedmetadata",
        () => els.preview.play().catch(() => {}),
        { once: true }
      );
    }
  }

  function stopPreview() {
    destroyPreview();
    if (els.preview) els.preview.style.display = "none";
    showPreviewPlaceholder("Diretta terminata");
  }

  async function pauseStream() {
    await fetch(cfg.pauseUrl, { method: "POST", headers: { Accept: "application/json" } });
    toast("Trasmissione in pausa");
  }

  async function stopStream() {
    const ok = confirm("Chiudere definitivamente la diretta?");
    if (!ok) return null;
    const res = await fetch(cfg.stopUrl, { method: "POST", headers: { Accept: "application/json" } });
    if (!res.ok) throw new Error("Errore chiusura");
    const data = await res.json();
    cfg.streamClosed = true;
    stopPreview();
    toast("Diretta chiusa");
    return data;
  }

  document.getElementById("btn-pause")?.addEventListener("click", () => pauseStream().catch((e) => toast(e.message)));
  document.getElementById("btn-stop")?.addEventListener("click", () => stopStream().catch((e) => toast(e.message)));

  async function shareLink() {
    const payload = {
      title: cfg.shareTitle,
      text: "Apri questo link per gestire il punteggio della diretta:",
      url: cfg.shareUrl
    };
    if (navigator.share) {
      try {
        await navigator.share(payload);
        return;
      } catch (err) {
        if (err.name === "AbortError") return;
      }
    }
    await copyLink();
  }

  async function copyLink() {
    try {
      await navigator.clipboard.writeText(cfg.shareUrl);
      toast("Link copiato");
    } catch (_) {
      prompt("Copia il link:", cfg.shareUrl);
    }
  }

  document.getElementById("btn-share")?.addEventListener("click", () => shareLink());
  document.getElementById("btn-copy")?.addEventListener("click", () => copyLink());

  bindPreviewEvents();
  if (!cfg.streamClosed && cfg.hlsUrl) {
    pollStatus();
  } else if (cfg.streamClosed) {
    stopPreview();
  }
  setInterval(pollStatus, 4000);
})();
