// ======================================================================
// controller.core.js  —  MÓDULO CENTRAL (VERSÃO FINAL)
// Projeto: HEP Flashcards
// Descrição: Estados globais, helpers, lógica central e integração de módulos.
// ======================================================================
// Contém:
//  ✔ Estados globais
//  ✔ Helpers (norm, waitMs, qs)
//  ✔ Similaridade segura (evita colisões "où est...")
//  ✔ bestCardFor()  → fallback, NÃO força mais sempre o primeiro card
//  ✔ Conexão do AUTO
//  ✔ speakSequenceForCard()
//  ✔ HIT_TARGET via combobox
//  ✔ init(), redrawCards()
//  ✔ fixTopHeight
//  ✔ Desbloqueio de áudio p/ iOS
// ======================================================================

(function(){

    // ----------------------------------------------------------------------
    // ESTADOS GLOBAIS
    // ----------------------------------------------------------------------
    window.FROM            = "ptbr";
    window.TO              = "fr";
    window._speakFromFirst = true;
    window.HIT_TARGET      = null;   // via combobox
    window.qt_cont         = 10;     // (mantido para compatibilidade)
    
    
    // ----------------------------------------------------------------------
    // HELPERS
    // ----------------------------------------------------------------------
    function norm(s){
        if (!s) return "";
        return s.toLowerCase()
            .normalize("NFD").replace(/[\u0300-\u036f]/g, "")
            .replace(/[^\p{L}\p{N}\s]/gu, "")
            .replace(/\s+/g, " ")
            .trim();
    }
    window.norm = norm;
    
    function waitMs(ms){ return new Promise(r=>setTimeout(r,ms)); }
    function qs(sel){ return document.querySelector(sel); }
    
    
    // ----------------------------------------------------------------------
    // Similaridade protegida contra colisões
    //  (usado só como *fallback* se fuzzyMatch não achar nada)
// ----------------------------------------------------------------------
    function similarityScore(a, b){
        if (!a || !b) return 0;
    
        const wa = a.split(/\s+/);
        const wb = b.split(/\s+/);
    
        let match = 0;
        for (let i = 0; i < wa.length; i++){
            if (wb.includes(wa[i])) match++;
        }
        return match / Math.max(wa.length, wb.length);
    }
    
    
    // ----------------------------------------------------------------------
    // Achar card "mais parecido" — APENAS fallback
    //  (o engine principal agora tenta fuzzyMatch card por card)
// ----------------------------------------------------------------------
    window.bestCardFor = function(spoken){
    
        if (!spoken) return null;
        const sNorm = norm(spoken);
        const all   = UI.getVisibleCards();

        if (!all || !all.length) return null;
    
        let best = null;
        let bestScore = 0;
    
        for (const c of all){
            const expected     = c.dataset.to || "";
            const expectedNorm = norm(expected);
            const score = similarityScore(sNorm, expectedNorm);
    
            // limite mínimo → evita marcar card errado
            if (score > bestScore && score >= 0.70){
                bestScore = score;
                best = c;
            }
        }
    
        return best;
    };
    
    
    // ======================================================================
    // AUTO → CONTROLLER
    // ======================================================================
    AutoPlayer.onGetVisibleCards = () => UI.getVisibleCards();
    AutoPlayer.onToast           = (msg,ms) => UI.toast(msg,ms);
    AutoPlayer.onUpdateStats     = () => UI.updateStats();
    
    AutoPlayer.onNextCard = (card) => {
        UI.setAutoplayCurrent(card);
        return card;
    };
    
    AutoPlayer.onRequestSpeakSequence = async(card)=>{
        UI.setAutoplayCurrent(card);
        return speakSequenceForCard(card);
    };
    
    
    // ======================================================================
    // SEQUÊNCIA DE FALA DO CARD
    // ======================================================================
    async function speakSequenceForCard(card){
        if (!card) return;

        // Remove bordas antigas
        card.classList.remove('card-spoken');

        const fromText = card.dataset.from || "";
        const toText   = card.dataset.to   || "";

        const rate  = parseFloat(qs("#selTtsRate")?.value || "1");
        const delay = parseInt(qs("#selAutoInterval")?.value || "2000");

        const langFrom = LANGS_BCP[window.FROM];
        const langTo   = LANGS_BCP[window.TO];

        // Adiciona borda grossa
        card.classList.add('card-speaking');
        try {
            if (window._speakFromFirst && fromText.trim()){
                await TtsEngine.speak(fromText, { langTag: langFrom, rate });
                await waitMs(delay);
            }
            if (toText.trim()){
                await TtsEngine.speak(toText, { langTag: langTo, rate });
            }
        } finally {
            card.classList.remove('card-speaking');
            card.classList.add('card-spoken');
        }
    }
    
    
    // ======================================================================
    // CONTROLLER PRINCIPAL
    // ======================================================================
    window.AppController = {};
    
    window.AppController.init = function(){
    
        // ------------------------------------------------------
        // HIT_TARGET (combobox de número de acertos)
        // ------------------------------------------------------
        const sel = qs("#selHitTarget");
        if (sel){
    
            window.HIT_TARGET = sel.value ? parseInt(sel.value) : null;
    
            sel.addEventListener("change", ()=>{
    
                window.HIT_TARGET = sel.value ? parseInt(sel.value) : null;
    
                // se desabilitou → zera contadores
                if (!window.HIT_TARGET && window.CARDS_DATA){
                    window.CARDS_DATA.forEach(c => c._count = 0);
                }
    
                UI.refreshCounters?.();
            });
        }
    
    
        // ------------------------------------------------------
        // Eventos gerais
        // ------------------------------------------------------
        if (window.bindUIEvents) bindUIEvents();
    
        // ------------------------------------------------------
        // STT
        // ------------------------------------------------------
        if (window.bindSTT) bindSTT();
    
    
        // ------------------------------------------------------
        // Render dos cards
        // ------------------------------------------------------
        const cards = CardsRepo.getAll();
    
        UI.renderLangCombos(window.FROM, window.TO);
        UI.renderCards(cards, { fromKey: window.FROM, toKey: window.TO });
    
        // switches iniciais
        window._speakFromFirst = qs("#chkSpeakFrom")?.checked ?? true;
        UI.updateShowPT(qs("#chkShowPT")?.checked);
        UI.updateShowLang(qs("#chkShowLang")?.checked);
    
        UI.updateStats();
    };
    
    
    // ======================================================================
    // REDESENHAR
    // ======================================================================
    window.redrawCards = function(){
    
        const cards = CardsRepo.getAll();
    
        UI.renderCards(cards, { fromKey: window.FROM, toKey: window.TO });
    
        UI.updateShowPT(qs("#chkShowPT")?.checked);
        UI.updateShowLang(qs("#chkShowLang")?.checked);
    
        UI.updateStats();
    };
    
    
    // ======================================================================
    // FIX TOP HEIGHT → evita sumir 4 primeiros cards
    // ======================================================================
    window.addEventListener("load", fixTopHeight);
    window.addEventListener("resize", fixTopHeight);
    
    function fixTopHeight(){
        const h = document.getElementById("topWrapper").offsetHeight;
        document.documentElement.style.setProperty("--top-height", h + "px");
    }
    
    
// ======================================================
// Atualiza apenas o ícone flutuante do microfone
// ======================================================
window.updateMicStatus = function(isOn){
    const icon = document.getElementById("micFloating");
    if (!icon) return;

    if (isOn){
        icon.classList.add("mic-on");
        icon.classList.remove("mic-off");
    } else {
        icon.classList.remove("mic-on");
        icon.classList.add("mic-off");
    }
};


    
    // ======================================================================
    // DESBLOQUEIO DE ÁUDIO NO iOS (necessário para beep funcionar)
    // ======================================================================
    (function(){
        let unlocked = false;
    
        function unlockAudio(){
            if (unlocked) return;
            unlocked = true;
    
            const a = document.getElementById("beep1");
            if (a){
                a.play().then(()=>{
                    a.pause();
                    a.currentTime = 0;
                    console.log("🔓 Áudio desbloqueado no iOS");
                }).catch(()=>{});
            }
    
            document.removeEventListener("touchstart", unlockAudio);
            document.removeEventListener("click", unlockAudio);
        }
    
        document.addEventListener("touchstart", unlockAudio, { once:true });
        document.addEventListener("click", unlockAudio, { once:true });
    
    })();
    
    
// ======================================================================
})();   // ← FIM
// ======================================================================
