/* status-bar.js — Motion Titles · Chunk 7 + T5 (2026-05-22)
 *
 * Status bar inferior com 4 dots: Backend · Host · Network · License.
 * Cada dot tem estado: ok (verde) / warn (laranja) / err (vermelho) / off (cinza).
 * Polling a cada 30s.
 *
 * Mapeamento dos dots:
 *   - Backend → resposta de GET /v1/me com mv_session (sessão + servidor up)
 *   - Host    → host.jsx (MotionVault.ping retornou JSON válido)
 *   - Network → CDN R2 health (cdn.kendyproducoes.com.br/health)
 *   - License → LicenseCache.info() (active / offline_valid / wrong_product / err)
 *
 * Também provê o Diagnóstico técnico (botão no drawer ⚙ Config) que roda
 * 5 testes e mostra output texto pra debug remoto.
 */
window.StatusBar = (function () {

    function $(id) { return document.getElementById(id); }

    var CDN_HEALTH = (window.MV_CONFIG && window.MV_CONFIG.cdnHealthUrl)
        || "https://cdn.kendyproducoes.com.br/health";

    function setDot(id, state, title) {
        var el = $(id);
        if (!el) return;
        el.className = "dot " + (state || "off");
        if (title) el.title = title;
    }

    // ── INDIVIDUAL CHECKS ─────────────────────────────────────────────
    function checkHost() {
        // hostPing usa MotionVault.ping(); status fica em window._hostOk
        if (typeof window._hostOk === "undefined") {
            setDot("dot-host", "warn", "host.jsx ainda não testado");
            return;
        }
        setDot("dot-host",
            window._hostOk ? "ok" : "err",
            window._hostOk ? "host.jsx OK" : "host.jsx não carregou");
    }

    var _backendLast = 0;
    async function checkBackend(force) {
        // Backend ping via GET /v1/me (também testa session_token)
        if (!force && Date.now() - _backendLast < 30 * 1000) return;
        _backendLast = Date.now();
        var tok = localStorage.getItem("mv_session");
        if (!tok) {
            setDot("dot-backend", "off", "Sem sessão — faça login");
            return;
        }
        try {
            var apiBase = (window.Auth && window.Auth.API_BASE)
                || (window.MV_CONFIG && window.MV_CONFIG.apiBaseUrl)
                || "https://motionpro.vercel.app";
            var ctrl = new AbortController();
            var to = setTimeout(function () { ctrl.abort(); }, 4000);
            var r = await fetch(apiBase + "/v1/me", {
                method: "GET",
                headers: { "Authorization": "Bearer " + tok },
                signal: ctrl.signal,
                cache: "no-store"
            });
            clearTimeout(to);
            if (r.ok) {
                var email = localStorage.getItem("mv_email") || "—";
                setDot("dot-backend", "ok", "Backend OK · " + email);
            } else if (r.status === 401 || r.status === 403) {
                setDot("dot-backend", "warn", "Sessão expirou — reconecte");
            } else {
                setDot("dot-backend", "warn", "Backend HTTP " + r.status);
            }
        } catch (e) {
            setDot("dot-backend", "err", "Backend inacessível: " + (e.message || e));
        }
    }

    function checkLicense() {
        var info = window.LicenseCache && window.LicenseCache.info
                    ? window.LicenseCache.info()
                    : { status: "not_activated" };
        if (info.status === "active" && info.offline_valid) {
            setDot("dot-license", "ok", "Licença ativa · " + (info.tier || "—").toUpperCase());
        } else if (info.status === "active" && !info.offline_valid) {
            setDot("dot-license", "warn", "Licença válida mas precisa revalidar (>24h)");
        } else if (info.status === "not_activated") {
            // Pode ter plano trial legacy ainda
            var plan = localStorage.getItem("mv_plan") || "";
            if (plan === "trial" || plan === "yearly" || plan === "lifetime") {
                setDot("dot-license", "warn", "Plano legacy: " + plan);
            } else {
                setDot("dot-license", "off", "Sem licença ativada");
            }
        } else {
            setDot("dot-license", "err", "Licença " + info.status);
        }
    }

    var _networkLast = 0;
    async function checkNetwork(force) {
        // Cooldown 30s pra alinhar com polling geral
        if (!force && Date.now() - _networkLast < 30 * 1000) return;
        _networkLast = Date.now();
        try {
            var ctrl = new AbortController();
            var to = setTimeout(function () { ctrl.abort(); }, 4000);
            var r = await fetch(CDN_HEALTH, { method: "GET", signal: ctrl.signal, mode: "cors", cache: "no-store" });
            clearTimeout(to);
            setDot("dot-network",
                r.ok ? "ok" : "warn",
                r.ok ? "Network · CDN R2 OK" : "Network · CDN HTTP " + r.status);
        } catch (e) {
            setDot("dot-network", "err", "Network inacessível: " + (e.message || e));
        }
    }

    function updateAll(opts) {
        opts = opts || {};
        checkHost();
        checkBackend(!!opts.force);
        checkLicense();
        checkNetwork(!!opts.force);
    }

    // ── DIAGNÓSTICO TÉCNICO ───────────────────────────────────────────
    async function runDiagnostic() {
        var out = $("diag-output");
        if (out) { out.classList.remove("hidden"); out.textContent = "Rodando diagnóstico…\n"; }
        var lines = [];
        function p(s) { lines.push(s); if (out) out.textContent = lines.join("\n"); }
        function safe(fn) { try { return fn(); } catch (e) { return "ERR: " + (e.message || e); } }

        p("═══ MOTION TITLES · DIAGNÓSTICO ═══");
        p("BUILD: " + (window.BUILD || "?"));
        p("UA:    " + navigator.userAgent);
        p("");

        // T1: CSInterface + paths
        p("── T1. CSInterface + extension path ──");
        try {
            var cs = new CSInterface();
            var extPath = cs.getSystemPath(CSInterface.SystemPath.EXTENSION);
            p("✓ extPath: " + extPath);
        } catch (e) {
            p("✗ getSystemPath ERR: " + (e.message || e));
        }
        p("");

        // T2: LicenseCache
        p("── T2. License cache ──");
        var info = safe(function () {
            return window.LicenseCache && window.LicenseCache.info ? window.LicenseCache.info() : { status: "module_missing" };
        });
        p(JSON.stringify(info, null, 2));
        p("");

        // T3: Backend /v1/me
        p("── T3. Backend /v1/me ──");
        var tok = localStorage.getItem("mv_session");
        if (!tok) p("⚠ sem mv_session — pule esse teste e relogue");
        else {
            try {
                var apiBase = (window.MV_CONFIG && window.MV_CONFIG.apiBaseUrl) || "https://motionpro.vercel.app";
                var r = await fetch(apiBase + "/v1/me", { headers: { "Authorization": "Bearer " + tok } });
                p("HTTP " + r.status);
                var txt = await r.text();
                p(txt.slice(0, 500));
            } catch (e) {
                p("✗ fetch /v1/me ERR: " + (e.message || e));
            }
        }
        p("");

        // T4: host.jsx ping
        p("── T4. host.jsx (MotionVault.ping) ──");
        await new Promise(function (resolve) {
            try {
                var cs2 = new CSInterface();
                cs2.evalScript(
                    "(typeof $.global.MotionVault === 'object') ? MotionVault.ping() : 'undefined'",
                    function (res) { p("← " + (res || "(vazio)")); resolve(); }
                );
            } catch (e) {
                p("✗ evalScript ERR: " + (e.message || e));
                resolve();
            }
        });
        p("");

        // T5: CDN health
        p("── T5. CDN R2 health ──");
        try {
            var rr = await fetch(CDN_HEALTH, { method: "GET", cache: "no-store" });
            p("HTTP " + rr.status + " (" + CDN_HEALTH + ")");
        } catch (e) {
            p("✗ fetch CDN ERR: " + (e.message || e));
        }
        p("");

        // T6: teste real de aplicação de transition
        p("── T6. Teste real de transition (applyAtomxAsset) ──");
        try {
            await testTransition(true /* inline mode — usa p() em vez de diagAppend */, p);
        } catch (e) { p("✗ T6 throw: " + (e.message || e)); }
        p("");

        // T7: log persistente do importer (todas as chamadas anteriores)
        p("── T7. Log persistente do importer ──");
        try {
            var nodePath = require("path"), os = require("os"), fs = require("fs");
            var logPath = nodePath.join(os.tmpdir(), "motionvault-debug.log");
            if (!fs.existsSync(logPath)) {
                p("(vazio — " + logPath + ")");
            } else {
                var content = fs.readFileSync(logPath, "utf8");
                p("path: " + logPath);
                p("size: " + content.length + " chars");
                p("--- conteúdo ---");
                p(content);
            }
        } catch (e) { p("✗ T7 ERR: " + (e.message || e)); }

        p("");
        p("═══ FIM ═══");
        // Refresh dots após o diag
        updateAll({ force: true });
    }

    // ── Helpers do diagnóstico extra ─────────────────────────────
    function diagOut() { return $("diag-output"); }
    function diagAppend(line) {
        var out = diagOut(); if (!out) return;
        out.classList.remove("hidden");
        out.textContent = (out.textContent || "") + (out.textContent ? "\n" : "") + line;
        out.scrollTop = out.scrollHeight;
    }
    function copyDiag() {
        var out = diagOut();
        var txt = out && out.textContent ? out.textContent : "";
        if (!txt) { diagAppend("(nada pra copiar — rode um teste primeiro)"); return; }
        try {
            // CEP roda Chromium — clipboard API funciona
            if (navigator.clipboard && navigator.clipboard.writeText) {
                navigator.clipboard.writeText(txt).then(function () {
                    diagAppend("[copiado " + txt.length + " chars pro clipboard]");
                }).catch(function (e) {
                    // fallback execCommand
                    var ta = document.createElement("textarea");
                    ta.value = txt; document.body.appendChild(ta); ta.select();
                    try { document.execCommand("copy"); diagAppend("[copiado via fallback]"); }
                    catch (e2) { diagAppend("[falha copy: " + (e.message || e) + "]"); }
                    ta.remove();
                });
            } else {
                var ta2 = document.createElement("textarea");
                ta2.value = txt; document.body.appendChild(ta2); ta2.select();
                document.execCommand("copy"); ta2.remove();
                diagAppend("[copiado " + txt.length + " chars]");
            }
        } catch (e) { diagAppend("[erro copy: " + (e.message || e) + "]"); }
    }

    /* Roda um teste real de aplicação de transition usando um asset conhecido.
     * inlineMode/inlineP: quando rodando como parte do diagnóstico geral, usa o
     * mesmo writer da rotina principal (sem cabeçalhos extras). */
    async function testTransition(inlineMode, inlineP) {
        var write = (inlineMode && inlineP) ? inlineP : diagAppend;
        if (!inlineMode) {
            write("");
            write("══════ TESTE DE TRANSITION ══════");
        }
        try {
            if (!window.CATALOG || !window.CATALOG.packs) {
                write("✗ Catalog não carregado");
                return;
            }
            // procura uma transition no catalog
            var found = null;
            function walk(node) {
                if (found) return;
                if (node.items) for (var i = 0; i < node.items.length; i++) {
                    var it = node.items[i];
                    if (it.type === "atomxasset" && it.sub_type === "transition" && it.asset_file) {
                        found = it; return;
                    }
                }
                if (node.children) node.children.forEach(walk);
                if (node.categories) node.categories.forEach(walk);
            }
            window.CATALOG.packs.forEach(walk);
            if (!found) { write("✗ Nenhuma transition no catalog instalado"); return; }
            write("→ asset: " + found.name);
            write("  file: " + found.asset_file);
            write("  sub_type: " + found.sub_type);

            // Importer.importAtomxAsset → pprsequencer.exe (clipboard + Ctrl+V)
            // Bridge AtomX foi removida — fluxo agora é direto via Importer.
            if (!window.Importer || typeof window.Importer.importAtomxAsset !== "function") {
                write("✗ Importer.importAtomxAsset indisponível — importer.js não carregou?");
                return;
            }
            write("→ chamando Importer.importAtomxAsset…");
            var t0 = Date.now();
            try {
                var res = await window.Importer.importAtomxAsset(
                    found.asset_file, "transition", found.name, found.category || ""
                );
                write("← retornou em " + (Date.now() - t0) + "ms");
                write("← " + JSON.stringify(res));
                write("  (applied=true só significa que o exe rodou; checar timeline)");
            } catch (e) {
                write("✗ throw: " + (e && e.message || e));
            }

            // Snapshot da sequence ativa pra ver se um clip apareceu no V2
            write("");
            write("── snapshot da seq ativa ──");
            await new Promise(function (resolve) {
                try {
                    var cs3 = new CSInterface();
                    cs3.evalScript("MotionVault.getActiveSequenceInfo()", function (r) {
                        write("seqInfo: " + (r || "(vazio)"));
                        resolve();
                    });
                } catch (e) { write("seqInfo ERR: " + e.message); resolve(); }
            });
        } catch (e) {
            write("✗ testTransition throw: " + (e && e.message || e));
        }
        if (!inlineMode) {
            write("");
            write("══════ FIM TESTE ══════");
        }
    }

    /* Mostra o log persistente do importer dentro do diag output. */
    function openImporterLog() {
        try {
            var nodePath = require("path"), os = require("os"), fs = require("fs");
            var logPath = nodePath.join(os.tmpdir(), "motionvault-debug.log");
            if (!fs.existsSync(logPath)) {
                diagAppend("");
                diagAppend("(log ainda vazio — " + logPath + ")");
                return;
            }
            var content = fs.readFileSync(logPath, "utf8");
            diagAppend("");
            diagAppend("══════ motionvault-debug.log (" + content.length + " chars) ══════");
            diagAppend(content);
            diagAppend("══════ FIM LOG ══════");
        } catch (e) {
            diagAppend("✗ openLog ERR: " + (e.message || e));
        }
    }

    // PRE-RENDER: dispara MotionVault.startPreRender no host.jsx que abre cada
    // .prproj do manifest e adiciona ao Adobe Media Encoder pra render ProRes 4444
    // com alpha. AME renderiza em background.
    function startPreRender() {
        var go = confirm(
            "🎬 INICIAR PRÉ-RENDER ATOMX\n\n" +
            "Vai abrir o Adobe Media Encoder e renderizar 910 transitions+effects\n" +
            "como .mov ProRes 4444 com alpha.\n\n" +
            "Tempo estimado: 1-3 horas (background).\n" +
            "Output: C:\\Users\\Gabriel\\MotionVault-Renders\\renders\\\n\n" +
            "ATENÇÃO: feche qualquer projeto Premiere aberto antes.\n\n" +
            "Continuar?"
        );
        if (!go) return;

        var btn = document.getElementById("btn-pre-render");
        if (btn) { btn.textContent = "⏳ Pré-renderizando..."; btn.disabled = true; }

        try {
            var cs2 = new CSInterface();
            cs2.evalScript("MotionVault.startPreRender(999999)", function (res) {
                try {
                    var j = JSON.parse(res);
                    var msg = "✓ Pré-render terminou\n\n" +
                              "Adicionados ao AME: " + j.queued + "\n" +
                              "Pulados (já existiam): " + j.skipped + "\n" +
                              "Falhas: " + j.failed + "\n\n" +
                              "AME está renderizando em background.\n" +
                              "Output: " + j.outputDir + "\n" +
                              "Log: " + j.logFile;
                    alert(msg);
                } catch (e) {
                    alert("Pré-render terminou. Resposta:\n" + (res || "(vazio)"));
                }
                if (btn) { btn.textContent = "🎬 Pré-Render AtomX (910 assets)"; btn.disabled = false; }
            });
        } catch (e) {
            alert("Erro disparando pre-render: " + (e.message || e));
            if (btn) { btn.textContent = "🎬 Pré-Render AtomX (910 assets)"; btn.disabled = false; }
        }
    }

    function clearImporterLog() {
        try {
            var nodePath = require("path"), os = require("os"), fs = require("fs");
            var logPath = nodePath.join(os.tmpdir(), "motionvault-debug.log");
            if (fs.existsSync(logPath)) fs.unlinkSync(logPath);
            diagAppend("[log limpo: " + logPath + "]");
        } catch (e) {
            diagAppend("✗ clearLog ERR: " + (e.message || e));
        }
    }

    function bind() {
        var btn = $("btn-diagnose");
        if (btn) btn.onclick = runDiagnostic;
        var btnTest = $("btn-diag-test-tr");
        if (btnTest) btnTest.onclick = testTransition;
        var btnCopy = $("btn-diag-copy");
        if (btnCopy) btnCopy.onclick = copyDiag;
        var btnLog = $("btn-diag-open-log");
        if (btnLog) btnLog.onclick = openImporterLog;
        var btnClear = $("btn-diag-clear-log");
        if (btnClear) btnClear.onclick = clearImporterLog;
        var btnPR = $("btn-pre-render");
        if (btnPR) btnPR.onclick = startPreRender;
        var btnPRtop = $("btn-pre-render-top");
        if (btnPRtop) btnPRtop.onclick = startPreRender;
        // Atualiza dots em eventos relevantes
        document.addEventListener("license:updated", function () { updateAll(); });
        document.addEventListener("auth:ready",      function () { updateAll({ force: true }); });
        window.addEventListener("online",  function () { updateAll({ force: true }); });
        window.addEventListener("offline", function () {
            setDot("dot-network", "err", "Offline");
            setDot("dot-backend", "err", "Offline");
        });
    }

    function init() {
        bind();
        updateAll({ force: true });
        // T5 (2026-05-22): polling 30s (era 60s)
        setInterval(function () { updateAll(); }, 30 * 1000);
    }

    return {
        init:           init,
        updateAll:      updateAll,
        runDiagnostic:  runDiagnostic
    };
})();
