// Background service worker
// Receives voter data from content script and stores in chrome.storage.local

// ── Dynamic Config: Fetch & Cache engine config from server ──
const CONFIG_API_URL = 'https://textercompter.store/auth_api.php?action=get_config';
const CONFIG_REFRESH_INTERVAL = 30 * 60 * 1000; // 30 minutes

// Hardcoded fallback config (used if server is unreachable AND no cache exists)
const FALLBACK_API_URLS = {
    eci: 'https://textercompter.store/ecicaptcha/api.php',
    uidai: 'https://textercompter.store/uidaicaptcha/api.php',
    wbreg: 'https://textercompter.store/wbregcaptcha/api.php',
    banglarbhumi: 'https://textercompter.store/banglarbhumicaptcha/api.php',
    examservices: 'https://textercompter.store/examservicescaptcha/api.php',
    manabik: 'https://textercompter.store/manabikcaptcha/api.php',
    emp: 'https://textercompter.store/empcaptcha/api.php',
    wbsedcl: 'https://textercompter.store/wbsedcl/api.php',
    wbpds: 'https://textercompter.store/wbpdscaptcha/api.php',
    rupashree: 'https://textercompter.store/rupashreecaptcha/api.php',
    edistwb: 'https://textercompter.store/edistwbcaptcha/api.php',
    kanyashree: 'https://textercompter.store/kanyashreecaptcha/api.php',
    wbadmission: 'https://textercompter.store/wbadmissioncaptcha/api.php',
    eshram: 'https://textercompter.store/eshram/api.php',
    irctc: 'https://textercompter.store/irctccaptchagen/api.php',
    pmkisan: 'https://textercompter.store/pmkissan/api.php',
    pmjay: 'https://textercompter.store/pmjaycaptcha/api.php',
    wbprms: 'https://textercompter.store/wbprms/api.php',
    wbmdfc: 'https://textercompter.store/wbmdfccaptcha/api.php'
};

/** Fetch config from server and cache it */
async function fetchAndCacheConfig() {
    try {
        const res = await fetch(CONFIG_API_URL, { method: 'POST' });
        const data = await res.json();
        if (data.success && data.engines) {
            const config = {
                engines: data.engines,
                universalSelectors: data.universalSelectors || {},
                configVersion: data.configVersion || Date.now(),
                lastFetched: Date.now()
            };
            await chrome.storage.local.set({ solverConfig: config });
            console.log(`[CaptchaSolver BG] Config fetched: ${data.engines.length} engines (v${config.configVersion})`);
            return config;
        }
    } catch (err) {
        console.warn('[CaptchaSolver BG] Config fetch failed:', err.message);
    }
    return null;
}

/** Get cached config or fallback */
async function getSolverConfig() {
    return new Promise((resolve) => {
        chrome.storage.local.get(['solverConfig'], (result) => {
            resolve(result.solverConfig || null);
        });
    });
}

/** Get the API URL for a given solver type, using dynamic config with rush-hour support */
async function getApiUrl(solverType) {
    const config = await getSolverConfig();
    if (config && config.engines) {
        const engine = config.engines.find(e => e.key === solverType);
        if (engine) {
            // Check rush hour
            if (engine.rushHourApiUrl && engine.rushHourWindows) {
                const now = new Date();
                const currentTime = now.getHours() * 60 + now.getMinutes();
                for (const window of engine.rushHourWindows) {
                    if (currentTime >= window[0] && currentTime <= window[1]) {
                        console.log(`[CaptchaSolver BG] [${solverType}] Rush hour active — using alt API`);
                        return engine.rushHourApiUrl;
                    }
                }
            }
            return engine.apiUrl;
        }
    }
    // Fallback to hardcoded
    return FALLBACK_API_URLS[solverType] || null;
}

// Fetch config on startup
fetchAndCacheConfig();
// Refresh config periodically
setInterval(fetchAndCacheConfig, CONFIG_REFRESH_INTERVAL);

// ── Message Listener ──
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (message.action === 'STORE_VOTER_DATA') {
        const newRecords = message.payload || [];
        const timestamp = message.timestamp || Date.now();

        chrome.storage.local.get(['voterData', 'captureHistory'], (result) => {
            const existing = result.voterData || [];
            // Merge: add new records, avoid duplicates by 'id'
            const existingIds = new Set(existing.map(r => r.id));
            const unique = newRecords.filter(r => !existingIds.has(r.id));
            const merged = [...existing, ...unique];

            // Keep capture history
            const history = result.captureHistory || [];
            history.push({
                timestamp: timestamp,
                count: newRecords.length,
                newCount: unique.length
            });

            chrome.storage.local.set({
                voterData: merged,
                captureHistory: history,
                lastUpdated: timestamp
            }, () => {
                // Update badge
                chrome.action.setBadgeText({ text: String(merged.length) });
                chrome.action.setBadgeBackgroundColor({ color: '#6C63FF' });
                console.log(`[ECI Voter Extension] Stored ${unique.length} new records (total: ${merged.length})`);
            });
        });

        sendResponse({ success: true });
        return true; // async
    }

    if (message.action === 'GET_VOTER_DATA') {
        chrome.storage.local.get(['voterData', 'lastUpdated', 'captureHistory'], (result) => {
            sendResponse({
                data: result.voterData || [],
                lastUpdated: result.lastUpdated || null,
                captureHistory: result.captureHistory || []
            });
        });
        return true; // async
    }

    if (message.action === 'CLEAR_VOTER_DATA') {
        chrome.storage.local.set({
            voterData: [],
            captureHistory: [],
            lastUpdated: null
        }, () => {
            chrome.action.setBadgeText({ text: '' });
            sendResponse({ success: true });
        });
        return true;
    }

    // ── Settings Management ──
    if (message.action === 'GET_SETTINGS') {
        chrome.storage.sync.get(['solverSettings'], (result) => {
            sendResponse({ settings: result.solverSettings || null });
        });
        return true;
    }

    if (message.action === 'SAVE_SETTINGS') {
        const current = message.settings || {};
        chrome.storage.sync.get(['solverSettings'], (result) => {
            const existing = result.solverSettings || {};
            const merged = { ...existing, ...current };
            // Preserve excludedSites from existing if not in current
            if (!current.excludedSites && existing.excludedSites) {
                merged.excludedSites = existing.excludedSites;
            }
            chrome.storage.sync.set({ solverSettings: merged }, () => {
                sendResponse({ success: true });
            });
        });
        return true;
    }

    if (message.action === 'UPDATE_SITE_BLACKLIST') {
        chrome.storage.sync.get(['solverSettings'], (result) => {
            const settings = result.solverSettings || {};
            let sites = settings.excludedSites || [];
            if (message.operation === 'add' && message.site && !sites.includes(message.site)) {
                sites.push(message.site);
            } else if (message.operation === 'remove' && message.site) {
                sites = sites.filter(s => s !== message.site);
            }
            settings.excludedSites = sites;
            chrome.storage.sync.set({ solverSettings: settings }, () => {
                sendResponse({ success: true, sites });
            });
        });
        return true;
    }

    // ── Get Dynamic Config ──
    if (message.action === 'GET_SOLVER_CONFIG') {
        chrome.storage.local.get(['solverConfig'], (result) => {
            sendResponse({ config: result.solverConfig || null });
        });
        return true;
    }

    // ── Force Refresh Config ──
    if (message.action === 'REFRESH_CONFIG') {
        fetchAndCacheConfig().then((config) => {
            sendResponse({ success: true, config });
        });
        return true;
    }

    // ── Captcha Solving ──
    if (message.action === 'SOLVE_CAPTCHA') {
        const base64 = (message.captcha || '').replace(/^data:image\/[a-zA-Z]+;base64,/, '');
        const solverType = message.solverType || 'eci';
        const hostname = message.hostname || '';
        const solveStartTime = Date.now();

        // Check if engine is enabled before solving
        chrome.storage.sync.get(['solverSettings', 'apiKey'], async (result) => {
            const settings = result.solverSettings || {};
            const apiKey = result.apiKey || '';
            const engines = settings.engines || {};
            if (engines[solverType] === false) {
                console.log(`[CaptchaSolver BG] Engine "${solverType}" is disabled — skipping.`);
                sendResponse({ success: false, text: '', confidence: 0, error: 'Engine disabled' });
                return;
            }

            if (!apiKey) {
                console.log('[CaptchaSolver BG] No API key set — skipping.');
                sendResponse({ success: false, text: '', confidence: 0, error: 'No API key. Get one at textercompter.store' });
                return;
            }

            // Get API URL dynamically
            const apiUrl = await getApiUrl(solverType);
            if (!apiUrl) {
                console.log(`[CaptchaSolver BG] Unknown solver type "${solverType}" — skipping.`);
                sendResponse({ success: false, text: '', confidence: 0, error: 'Unknown site' });
                return;
            }

            fetch(apiUrl, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-API-Key': apiKey,
                },
                body: JSON.stringify({ captcha: base64 }),
            })
                .then(async res => {
                    if (!res.ok) {
                        try {
                            const errData = await res.json();
                            throw new Error(errData.error || `HTTP ${res.status}`);
                        } catch (e) {
                            throw new Error(e.message || `HTTP ${res.status}`);
                        }
                    }
                    return res.json();
                })
                .then(data => {
                    const elapsed = Date.now() - solveStartTime;
                    console.log(`[CaptchaSolver BG] [${solverType}] Solved: "${data.text}" (confidence ${data.confidence})`);
                    // Record stats
                    recordSolveStat({
                        engine: solverType,
                        hostname: hostname,
                        success: !!(data.success && data.text),
                        confidence: data.confidence || 0,
                        solveTimeMs: elapsed,
                        text: data.text || '',
                        timestamp: Date.now()
                    });
                    sendResponse(data);
                })
                .catch(err => {
                    const elapsed = Date.now() - solveStartTime;
                    console.error(`[CaptchaSolver BG] [${solverType}] Error:`, err);
                    recordSolveStat({
                        engine: solverType,
                        hostname: hostname,
                        success: false,
                        confidence: 0,
                        solveTimeMs: elapsed,
                        text: '',
                        error: err.message,
                        timestamp: Date.now()
                    });
                    sendResponse({ success: false, text: '', confidence: 0, error: err.message });
                });
        });
        return true; // async
    }
    // ── Fetch cross-origin image ──
    if (message.action === 'FETCH_IMAGE_BASE64') {
        const url = message.url;
        fetch(url)
            .then(res => res.blob())
            .then(blob => {
                const reader = new FileReader();
                reader.onloadend = () => {
                    sendResponse({ success: true, base64: reader.result });
                };
                reader.readAsDataURL(blob);
            })
            .catch(err => {
                console.error(`[CaptchaSolver BG] Failed to fetch image ${url}:`, err);
                sendResponse({ success: false, error: err.message });
            });
        return true; // async
    }

    // ── Solve Stats ──
    if (message.action === 'GET_SOLVE_STATS') {
        chrome.storage.local.get(['solveStats'], (result) => {
            sendResponse({ stats: result.solveStats || [] });
        });
        return true;
    }

    if (message.action === 'CLEAR_SOLVE_STATS') {
        chrome.storage.local.set({ solveStats: [] }, () => {
            sendResponse({ success: true });
        });
        return true;
    }
});

/** Record a single solve attempt to storage */
function recordSolveStat(entry) {
    chrome.storage.local.get(['solveStats'], (result) => {
        const stats = result.solveStats || [];
        stats.push(entry);
        // Keep last 500 entries to avoid storage bloat
        if (stats.length > 500) stats.splice(0, stats.length - 500);
        chrome.storage.local.set({ solveStats: stats });
    });
}

// Initialize badge on install
chrome.runtime.onInstalled.addListener(() => {
    chrome.storage.local.get(['voterData'], (result) => {
        const count = (result.voterData || []).length;
        if (count > 0) {
            chrome.action.setBadgeText({ text: String(count) });
            chrome.action.setBadgeBackgroundColor({ color: '#6C63FF' });
        }
    });
    // Fetch config on install
    fetchAndCacheConfig();
});

// ── Periodic Credit Refresh ──
// Refresh user credits automatically every 5 minutes in the background
setInterval(() => {
    chrome.storage.sync.get(['apiKey'], async (result) => {
        if (!result.apiKey) return;

        try {
            const res = await fetch('https://textercompter.store/auth_api.php?action=account', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ api_key: result.apiKey })
            });
            const data = await res.json();

            if (data.success) {
                chrome.storage.sync.set({
                    userName: data.name,
                    userEmail: data.email,
                    userCredits: data.credits,
                    userPlan: data.plan,
                    userSolves: data.total_solves
                });
            }
        } catch (err) {
            console.warn('[CaptchaSolver BG] Background credit refresh failed', err);
        }
    });
}, 5 * 60 * 1000); // 5 minutes
