// background.js
let pendingFills = {}; 
let baseIconData = null;   
let activeIconData = null; 

async function generateIconCache() {
    try {
        const res = await fetch("icon.png"); 
        if (!res.ok) throw new Error("Icon missing");
        const blob = await res.blob();
        const bitmap = await createImageBitmap(blob);
        
        const canvas = new OffscreenCanvas(32, 32);
        const ctx = canvas.getContext('2d');
        
        ctx.drawImage(bitmap, 0, 0, 32, 32);
        baseIconData = ctx.getImageData(0, 0, 32, 32);
        
        ctx.fillStyle = "rgba(0,0,0,0.4)";
        ctx.fillRect(0, 0, 32, 32);
        ctx.shadowColor = "rgba(0,0,0,0.9)";
        ctx.shadowBlur = 6;
        ctx.beginPath(); ctx.arc(23, 23, 9, 0, 2 * Math.PI); ctx.fillStyle = '#10b981'; ctx.fill();
        ctx.shadowBlur = 0;
        ctx.beginPath(); ctx.moveTo(17, 23); ctx.lineTo(21, 27); ctx.lineTo(28, 18);
        ctx.strokeStyle = 'white'; ctx.lineWidth = 3; ctx.stroke();
        
        activeIconData = ctx.getImageData(0, 0, 32, 32);
    } catch (e) {
        console.warn("AutoFiller GJ: Arquivo 'icon.png' não encontrado. Usando fallback de texto.");
    }
}

generateIconCache();

async function setDynamicIcon(tabId, hasModel) {
    const callback = () => { let err = chrome.runtime.lastError; }; 
    
    if (hasModel) {
        if (activeIconData) {
            chrome.action.setIcon({ imageData: activeIconData, tabId: tabId }, callback);
            chrome.action.setBadgeText({ text: "", tabId: tabId }, callback);
        } else {
            chrome.action.setBadgeText({ text: "✔", tabId: tabId }, callback);
            chrome.action.setBadgeBackgroundColor({ color: "#10b981", tabId: tabId }, callback);
        }
    } else {
        if (baseIconData) {
            chrome.action.setIcon({ imageData: baseIconData, tabId: tabId }, callback);
        }
        chrome.action.setBadgeText({ text: "", tabId: tabId }, callback);
    }
}

async function updateBadge(tabId, url) {
    if (!url || url.startsWith("chrome://")) { 
        chrome.action.setBadgeText({ text: "", tabId: tabId }, () => { let err = chrome.runtime.lastError; }); 
        return; 
    }
    const data = await chrome.storage.local.get({ zt_models: [] });
    const hasModel = data.zt_models.some(m => url.includes(m.url));
    await setDynamicIcon(tabId, hasModel);
}

chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
    if (changeInfo.url || changeInfo.status === 'complete') {
        if (tab.url) updateBadge(tabId, tab.url);
    }
    
    if (changeInfo.status === 'complete' && pendingFills[tabId]) {
        const fields = pendingFills[tabId];
        delete pendingFills[tabId];
        setTimeout(() => injectScript(tabId, fields), 1000); 
    }
});

chrome.tabs.onActivated.addListener(async (activeInfo) => {
    const tab = await chrome.tabs.get(activeInfo.tabId);
    if (tab.url) updateBadge(tab.id, tab.url);
});

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    if (request.action === "runModel") {
        executeModel(request.model);
        sendResponse({status: "ok"});
    }
    return true;
});

async function executeModel(model) {
    const tabs = await chrome.tabs.query({});
    const existingTab = tabs.find(t => t.url && t.url.includes(model.url));

    if (existingTab) {
        await chrome.windows.update(existingTab.windowId, { focused: true });
        await chrome.tabs.update(existingTab.id, { active: true });
        injectScript(existingTab.id, model.fields);
    } else {
        const newTab = await chrome.tabs.create({ url: model.fullUrl });
        pendingFills[newTab.id] = model.fields;
    }
}

function injectScript(tabId, actions) {
    chrome.scripting.executeScript({
        target: { tabId: tabId },
        func: async (formActions) => {
            async function processVariables(text) {
                if (!text) return text;
                const now = new Date();
                const pad = n => n.toString().padStart(2, '0');
                const formatDate = d => `${pad(d.getDate())}/${pad(d.getMonth()+1)}/${d.getFullYear()}`;
                let res = text;
                res = res.replace(/\{\{data_hoje\}\}/g, formatDate(now));
                res = res.replace(/\{\{hora_atual\}\}/g, `${pad(now.getHours())}:${pad(now.getMinutes())}`);
                const days = ['Domingo','Segunda-feira','Terça-feira','Quarta-feira','Quinta-feira','Sexta-feira','Sábado'];
                res = res.replace(/\{\{dia_semana\}\}/g, days[now.getDay()]);
                let ontem = new Date(now); ontem.setDate(ontem.getDate() - 1);
                res = res.replace(/\{\{data_ontem\}\}/g, formatDate(ontem));
                let amanha = new Date(now); amanha.setDate(amanha.getDate() + 1);
                res = res.replace(/\{\{data_amanha\}\}/g, formatDate(amanha));
                res = res.replace(/\{\{url_atual\}\}/g, window.location.href);
                if (res.includes('{{clipboard}}')) {
                    try { const clipText = await navigator.clipboard.readText(); res = res.replace(/\{\{clipboard\}\}/g, clipText); } 
                    catch(e) { console.warn("Falha ao ler clipboard", e); }
                }
                const askRegex = /\{\{ask:([^}]+)\}\}/g; let match;
                while ((match = askRegex.exec(res)) !== null) { res = res.replace(match[0], prompt(`AutoFiller Pergunta:\n${match[1]}`) || ""); }
                return res;
            }

            for (const action of formActions) {
                const type = action.type || 'fill';
                if (type === 'wait') {
                    // A nova interface já envia o valor final calculado em milissegundos
                    const ms = action.delay || 1000;
                    await new Promise(r => setTimeout(r, ms));
                    continue;
                }
                const el = document.querySelector(action.selector);
                if (!el) continue;
                if (type === 'click') { el.click(); continue; }
                if (type === 'fill') {
                    const finalValue = await processVariables(action.value);
                    if (el.isContentEditable) {
                        el.focus(); document.execCommand('insertText', false, finalValue); continue;
                    }
                    if (el.type === 'radio' || el.type === 'checkbox') {
                        el.checked = (el.value === finalValue || finalValue === "true");
                    } else {
                        const nativeTextAreaValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, "value")?.set;
                        const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")?.set;
                        if (el.tagName === 'TEXTAREA' && nativeTextAreaValueSetter) nativeTextAreaValueSetter.call(el, finalValue);
                        else if (el.tagName === 'INPUT' && nativeInputValueSetter) nativeInputValueSetter.call(el, finalValue);
                        else el.value = finalValue; 
                    }
                    el.dispatchEvent(new Event('input', { bubbles: true }));
                    el.dispatchEvent(new Event('change', { bubbles: true }));
                    el.dispatchEvent(new Event('blur', { bubbles: true }));
                    el.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, key: 'Enter', keyCode: 13 }));
                    if (typeof tinymce !== 'undefined' && el.id) {
                        const editor = tinymce.get(el.id);
                        if (editor) editor.setContent(finalValue.replace(/\n/g, '<br>'));
                    }
                }
            }
        },
        args: [actions]
    });
}

function buildContextMenus() {
    chrome.contextMenus.removeAll(() => {
        chrome.storage.local.get({ zt_models: [] }, (data) => {
            const models = data.zt_models;
            if (!models || models.length === 0) return;
            chrome.contextMenus.create({ id: "autofiller_root", title: "⚡ AutoFiller GJ", contexts: ["editable"] });
            const grouped = models.reduce((acc, m) => {
                const g = m.group || "Gerais"; if (!acc[g]) acc[g] = []; acc[g].push(m); return acc;
            }, {});
            for (const [groupName, groupModels] of Object.entries(grouped)) {
                const groupId = "group_" + groupName;
                chrome.contextMenus.create({ id: groupId, parentId: "autofiller_root", title: groupName, contexts: ["editable"] });
                groupModels.forEach(m => {
                    chrome.contextMenus.create({ id: "model_" + m.id, parentId: groupId, title: m.name, contexts: ["editable"] });
                });
            }
        });
    });
}

chrome.runtime.onInstalled.addListener(buildContextMenus);
chrome.storage.onChanged.addListener((changes) => { if (changes.zt_models) buildContextMenus(); });

chrome.contextMenus.onClicked.addListener(async (info, tab) => {
    if (info.menuItemId.startsWith("model_")) {
        const modelId = info.menuItemId.replace("model_", "");
        const data = await chrome.storage.local.get({ zt_models: [] });
        const model = data.zt_models.find(m => m.id === modelId);
        if (model) {
            const actionsArr = model.fields.filter(f => f.type !== 'wait' && f.type !== 'click' && f.value).map(f => f.value);
            chrome.scripting.executeScript({
                target: { tabId: tab.id },
                func: async (textArray) => {
                    async function processVariables(text) {
                        if (!text) return text;
                        const now = new Date(); const pad = n => n.toString().padStart(2, '0');
                        const formatDate = d => `${pad(d.getDate())}/${pad(d.getMonth()+1)}/${d.getFullYear()}`;
                        let res = text;
                        res = res.replace(/\{\{data_hoje\}\}/g, formatDate(now)); res = res.replace(/\{\{hora_atual\}\}/g, `${pad(now.getHours())}:${pad(now.getMinutes())}`);
                        const days = ['Domingo','Segunda-feira','Terça-feira','Quarta-feira','Quinta-feira','Sexta-feira','Sábado']; res = res.replace(/\{\{dia_semana\}\}/g, days[now.getDay()]);
                        let ontem = new Date(now); ontem.setDate(ontem.getDate() - 1); res = res.replace(/\{\{data_ontem\}\}/g, formatDate(ontem));
                        let amanha = new Date(now); amanha.setDate(amanha.getDate() + 1); res = res.replace(/\{\{data_amanha\}\}/g, formatDate(amanha));
                        res = res.replace(/\{\{url_atual\}\}/g, window.location.href);
                        if (res.includes('{{clipboard}}')) { try { res = res.replace(/\{\{clipboard\}\}/g, await navigator.clipboard.readText()); } catch(e) {} }
                        const askRegex = /\{\{ask:([^}]+)\}\}/g; let match;
                        while ((match = askRegex.exec(res)) !== null) { res = res.replace(match[0], prompt(`AutoFiller Pergunta:\n${match[1]}`) || ""); }
                        return res;
                    }
                    const rawText = textArray.join('\n\n');
                    const text = await processVariables(rawText);
                    const activeEl = document.activeElement;
                    if (activeEl && (activeEl.isContentEditable || activeEl.tagName === 'TEXTAREA' || activeEl.tagName === 'INPUT')) {
                        if (activeEl.isContentEditable) { document.execCommand('insertText', false, text); } 
                        else {
                            const start = activeEl.selectionStart; const end = activeEl.selectionEnd; const currentText = activeEl.value;
                            const nativeSetter = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(activeEl), "value")?.set;
                            const newText = currentText.substring(0, start) + text + currentText.substring(end);
                            if (nativeSetter) nativeSetter.call(activeEl, newText); else activeEl.value = newText;
                            activeEl.selectionStart = activeEl.selectionEnd = start + text.length;
                            activeEl.dispatchEvent(new Event('input', { bubbles: true })); activeEl.dispatchEvent(new Event('change', { bubbles: true }));
                        }
                    }
                },
                args: [actionsArr]
            });
        }
    }
});