(function () {
    const $ = (sel, root = document) => root.querySelector(sel);
    const $$ = (sel, root = document) => Array.from(root.querySelectorAll(sel));

    const logContainer = $("#logContainer");
    if (!logContainer) return;

    const displayLevelForm = $("#displayLevelForm");
    const searchForm = $("#searchForm");
    const queryInput = $("#query");
    const levelSelect = $("#level");
    const logScroll = $("#logScroll");

    // toolbar
    const btnLive = $("#btn-live");
    const btnAuto = $("#btn-autoscroll");
    const btnWrap = $("#btn-wrap");
    const fontSelect = $("#font-size");
    const btnCopy = $("#btn-copy");
    const btnDownload = $("#btn-download");

    // konfiguracja
    const POLL_MS = 1000;
    const ORDER_NEWEST_FIRST = true; // najnowsze na GÓRZE (backend już odwraca)
    const TOL = 40; // tolerancja (px) od krawędzi, aby uznać, że jesteśmy „przy krawędzi”

    // state
    let selectedLevel = levelSelect ? levelSelect.value : "INFO";
    let pollTimer = null;
    let live = true;

    // autoscroll: ON domyślnie
    let autoScroll = true;
    // gdy użytkownik ręcznie wyłączy — blokujemy automatyczne włączanie
    let autoLockByUser = false;
    // gdy autoscroll wyłączył się przez przewinięcie — możemy go automatycznie przywracać
    let autoDisabledBy = null; // null | 'scroll' | 'user'

    let wrapped = false;
    let lastPayload = "";
    let debounceTimer;

    function setUrlParam(key, val) {
        const url = new URL(window.location.href);
        if (val === "" || val == null) url.searchParams.delete(key);
        else url.searchParams.set(key, val);
        window.history.replaceState(null, "", url.toString());
    }

    function highlight() {
        if (window.hljs && typeof window.hljs.highlightElement === "function") {
            window.hljs.highlightElement(logContainer);
        }
    }

    function setEmptyState(on) {
        $("#logEmpty")?.classList.toggle("d-none", !on);
        logContainer.classList.toggle("d-none", on);
    }

    function refreshBtnLive() {
        if (!btnLive) return;
        btnLive.classList.toggle("btn-outline-light", live);
        btnLive.classList.toggle("btn-danger", !live);
        btnLive.textContent = live
            ? (btnLive.dataset.onText || "Live ON")
            : (btnLive.dataset.offText || "Live OFF");
    }

    function refreshBtnAuto() {
        if (!btnAuto) return;
        btnAuto.classList.toggle("btn-outline-secondary", !autoScroll);
        btnAuto.classList.toggle("btn-light", autoScroll);
        btnAuto.textContent = autoScroll ? "Auto-scroll" : "Auto-scroll (OFF)";
    }

    function scrollToEdgeIfNeeded() {
        if (!autoScroll) return;
        if (ORDER_NEWEST_FIRST) {
            // najnowsze na górze -> krawędź to top
            logScroll.scrollTop = 0;
        } else {
            // klasyczny tail -> krawędź to dół
            logScroll.scrollTop = logScroll.scrollHeight;
        }
    }

    function applyText(content) {
        lastPayload = content || "";
        setEmptyState(!lastPayload.length);
        logContainer.textContent = lastPayload;
        highlight();

        // tylko gdy autoscroll jest aktywny, przeskakujemy do krawędzi
        scrollToEdgeIfNeeded();
    }

    async function copyToClipboard(text) {
        try {
            if (navigator.clipboard && typeof navigator.clipboard.writeText === "function") {
                await navigator.clipboard.writeText(text);
                return true;
            }
        } catch (_) { /* fallback below */ }

        // Fallback dla HTTP/nieobsługiwanych środowisk
        const ta = document.createElement("textarea");
        ta.value = text;
        ta.style.position = "fixed";
        ta.style.top = "-1000px";
        ta.style.left = "-1000px";
        ta.setAttribute("readonly", "");
        document.body.appendChild(ta);
        ta.select();
        ta.setSelectionRange(0, ta.value.length);
        let ok = false;
        try {
            ok = document.execCommand("copy");
        } catch (_) {
            ok = false;
        }
        document.body.removeChild(ta);
        return ok;
    }

    function loadLogs({ silent = false } = {}) {
        const query = queryInput ? queryInput.value : "";
        const url = `/logs-data?level=${encodeURIComponent(selectedLevel)}&query=${encodeURIComponent(query)}`;
        return fetch(url)
            .then(res => res.ok ? res.json() : Promise.reject(res.status))
            .then(data => {
                // backend już zwraca newest-first; nie odwracaj kolejności
                const lines = Array.isArray(data.logs) ? data.logs.slice() : [];
                const text = lines.join("\n");
                applyText(text);
            })
            .catch(() => {
                if (!silent) window.showToast?.({ text: "Błąd ładowania logów", variant: "danger" });
            });
    }

    function startPolling() {
        stopPolling();
        if (!live) return;
        pollTimer = setInterval(() => loadLogs({ silent: true }), POLL_MS);
    }
    function stopPolling() {
        if (pollTimer) clearInterval(pollTimer);
        pollTimer = null;
    }

    // wyszukiwarka — enter lub debounce 400ms
    searchForm?.addEventListener("submit", (e) => {
        e.preventDefault();
        setUrlParam("query", queryInput.value || "");
        loadLogs();
    });
    queryInput?.addEventListener("input", () => {
        clearTimeout(debounceTimer);
        debounceTimer = setTimeout(() => {
            setUrlParam("query", queryInput.value || "");
            loadLogs({ silent: true });
        }, 400);
    });

    // --- TOOLBAR ---
    btnLive?.addEventListener("click", () => {
        live = !live;
        refreshBtnLive();
        window.showToast?.({
            text: live ? "Live tail: włączony" : "Live tail: wyłączony",
            variant: live ? "dark" : "warning"
        });
        live ? startPolling() : stopPolling();
    });
    refreshBtnLive();

    btnAuto?.addEventListener("click", () => {
        // ręczne przełączenie blokuje/odblokowuje auto włączanie
        autoScroll = !autoScroll;
        autoLockByUser = !autoScroll; // jeśli wyłączasz przyciskiem — zablokuj auto re-enable
        autoDisabledBy = autoScroll ? null : "user";
        refreshBtnAuto();

        window.showToast?.({
            text: autoScroll ? "Auto-scroll: ON" : "Auto-scroll: OFF (ręcznie)",
            variant: "info"
        });

        if (autoScroll) {
            // po włączeniu — przeskocz do krawędzi
            scrollToEdgeIfNeeded();
        }
    });
    refreshBtnAuto();

    btnWrap?.addEventListener("click", () => {
        wrapped = !wrapped;
        btnWrap.classList.toggle("btn-outline-secondary", !wrapped);
        btnWrap.classList.toggle("btn-light", wrapped);
        logContainer.style.whiteSpace = wrapped ? "pre-wrap" : "pre";
    });

    fontSelect?.addEventListener("change", () => {
        logContainer.style.fontSize = fontSelect.value;
    });

    btnCopy?.addEventListener("click", async () => {
        const ok = await copyToClipboard(lastPayload || "");
        window.showToast?.({
            text: ok ? "Skopiowano log do schowka." : "Nie udało się skopiować.",
            variant: ok ? "success" : "danger"
        });
    });

    btnDownload?.addEventListener("click", () => {
        const blob = new Blob([lastPayload || ""], { type: "text/plain;charset=utf-8" });
        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = url; a.download = `app.log.view.txt`; a.click();
        URL.revokeObjectURL(url);
    });

    // --- SMART AUTOSCROLL GUARD ---
    // 1) auto-wyłączenie gdy oddalimy się od krawędzi
    // 2) auto-włączenie gdy wrócimy do krawędzi, ale tylko jeśli nie zablokowano przyciskiem
    let scrollTicking = false; // micro-raf guard
    logScroll.addEventListener("scroll", () => {
        if (scrollTicking) return;
        scrollTicking = true;
        requestAnimationFrame(() => {
            scrollTicking = false;

            if (ORDER_NEWEST_FIRST) {
                // krawędź to góra (top)
                const atTop = logScroll.scrollTop <= TOL;
                const farFromTop = logScroll.scrollTop > TOL;

                // 1) gdy uciekasz od góry — wyłącz auto, jeśli było włączone
                if (farFromTop && autoScroll) {
                    autoScroll = false;
                    autoDisabledBy = "scroll";
                    refreshBtnAuto();
                    window.showToast?.({ text: "Auto-scroll: OFF (przewijanie)", variant: "info" });
                }

                // 2) gdy wracasz na samą górę — automatycznie włącz, jeśli nie ma blokady usera
                if (atTop && !autoScroll && !autoLockByUser && autoDisabledBy === "scroll") {
                    autoScroll = true;
                    autoDisabledBy = null;
                    refreshBtnAuto();
                    // upewnij się, że trzymamy top
                    logScroll.scrollTop = 0;
                    window.showToast?.({ text: "Auto-scroll: ON (powrót na górę)", variant: "info" });
                }
            } else {
                // klasyczny tail — krawędź to dół
                const distanceFromBottom = logScroll.scrollHeight - logScroll.clientHeight - logScroll.scrollTop;
                const atBottom = distanceFromBottom <= TOL;
                const farFromBottom = distanceFromBottom > TOL;

                if (farFromBottom && autoScroll) {
                    autoScroll = false;
                    autoDisabledBy = "scroll";
                    refreshBtnAuto();
                    window.showToast?.({ text: "Auto-scroll: OFF (przewijanie)", variant: "info" });
                }
                if (atBottom && !autoScroll && !autoLockByUser && autoDisabledBy === "scroll") {
                    autoScroll = true;
                    autoDisabledBy = null;
                    refreshBtnAuto();
                    logScroll.scrollTop = logScroll.scrollHeight;
                    window.showToast?.({ text: "Auto-scroll: ON (powrót na dół)", variant: "info" });
                }
            }
        });
    }, { passive: true });

    // Start
    loadLogs().then(() => startPolling());

    // sprzątanie
    window.addEventListener("beforeunload", () => {
        stopPolling();
    });
})();
