(() => {
    const root = document.getElementById("mr-action-runs");
    if (!(root instanceof HTMLElement)) {
        return;
    }
    const project = root.dataset.project || "";
    const runIds = (root.dataset.runIds || "")
        .split(",")
        .map((id) => id.trim())
        .filter(Boolean);
    if (!project || runIds.length === 0) {
        return;
    }

    const applyProgress = (payload) => {
        const item = root.querySelector(`[data-run-id="${payload.run_id}"]`);
        if (!(item instanceof HTMLElement)) {
            return;
        }
        const status = item.querySelector("[data-run-status]");
        const bar = item.querySelector("[data-run-bar]");
        if (status) {
            status.textContent = payload.message || "";
        }
        if (bar instanceof HTMLElement) {
            const pct = Math.max(0, Math.min(100, Math.round((payload.fraction ?? 0) * 100)));
            bar.style.width = `${pct}%`;
            bar.setAttribute("aria-valuenow", String(pct));
            bar.classList.remove("bg-success", "bg-danger");
            if (payload.done && payload.ok === true) {
                bar.classList.add("bg-success");
            } else if (payload.done && payload.ok === false) {
                bar.classList.add("bg-danger");
            }
        }
        return Boolean(payload.done);
    };

    const pollOnce = async () => {
        const params = new URLSearchParams({ project, ids: runIds.join(",") });
        const resp = await fetch(`/mr/runs?${params.toString()}`, {
            headers: { Accept: "application/json" },
        });
        if (!resp.ok) {
            return true;
        }
        const body = await resp.json();
        const runs = Array.isArray(body.runs) ? body.runs : [];
        let allDone = runs.length > 0;
        for (const run of runs) {
            if (!applyProgress(run)) {
                allDone = false;
            }
        }
        return allDone;
    };

    const preferSSE = typeof EventSource === "function";
    if (preferSSE) {
        const sources = runIds.map((runId) => {
            const params = new URLSearchParams({ project });
            const source = new EventSource(`/mr/runs/${encodeURIComponent(runId)}/events?${params}`);
            source.onmessage = (event) => {
                try {
                    const payload = JSON.parse(event.data);
                    if (applyProgress(payload)) {
                        source.close();
                    }
                } catch {
                    source.close();
                }
            };
            source.onerror = () => {
                source.close();
            };
            return source;
        });
        window.addEventListener(
            "beforeunload",
            () => {
                for (const source of sources) {
                    source.close();
                }
            },
            { once: true },
        );
        return;
    }

    const poll = async () => {
        try {
            const done = await pollOnce();
            if (!done) {
                window.setTimeout(poll, 1000);
            }
        } catch {
            window.setTimeout(poll, 2000);
        }
    };
    poll();
})();