// sw.js - Service Worker para funcionalidade Offline (Aprimorado pelo Cometê)

const CACHE_NAME = 'gestao-pro-cache-v3'; // Versão do cache para forçar atualização
const DATA_CACHE_NAME = 'gestao-pro-data-v3'; // Cache para dados

const urlsToCache = [
    '/',
    '/index.html',
    '/login.html',
    '/style.css',
    '/script.js',
    '/login.js',
    '/api.js', // Adicionado o novo arquivo api.js
    'https://cdn.tailwindcss.com',
    'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap',
    'https://fonts.googleapis.com',
    'https://fonts.gstatic.com',
    'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css',
    'https://cdn.jsdelivr.net/npm/chart.js',
    'https://cdn.jsdelivr.net/npm/localforage@1.10.0/dist/localforage.min.js' // Adicionado localforage
    // Adicione outras URLs de recursos estáticos que você usa regularmente
];

// Instalação: Cacheia os recursos estáticos da aplicação (App Shell)
self.addEventListener('install', event => {
    console.log('[SW] Install event. Caching app shell...');
    event.waitUntil(
        caches.open(CACHE_NAME)
            .then(cache => {
                return cache.addAll(urlsToCache);
            })
            .then(() => self.skipWaiting()) // Força o Service Worker a ativar imediatamente
            .catch(error => console.error('[SW] Failed to cache app shell:', error))
    );
});

// Ativação: Limpa caches antigos de versões anteriores
self.addEventListener('activate', event => {
    console.log('[SW] Activate event. Cleaning old caches...');
    event.waitUntil(
        caches.keys().then(cacheNames => {
            return Promise.all(
                cacheNames.map(cacheName => {
                    if (cacheName !== CACHE_NAME && cacheName !== DATA_CACHE_NAME) {
                        console.log('[SW] Deleting old cache:', cacheName);
                        return caches.delete(cacheName);
                    }
                })
            );
        }).then(() => {
            console.log('[SW] Old caches cleared. Claiming clients.');
            return self.clients.claim(); // Garante que o Service Worker assume o controle dos clientes imediatamente
        }).catch(error => console.error('[SW] Failed to activate or clear old caches:', error))
    );
});

// Interceptação de requisições de rede
self.addEventListener('fetch', event => {
    const requestUrl = new URL(event.request.url);

    // Estratégia Cache-First para recursos do App Shell
    const isAppShellResource = urlsToCache.some(url => event.request.url.includes(url.replace(/\//g, '')));
    if (event.request.mode === 'navigate' || isAppShellResource) {
        event.respondWith(
            caches.match(event.request).then(response => {
                return response || fetch(event.request).catch(() => {
                    // Fallback para página offline se navegação falhar e não estiver em cache
                    if (event.request.mode === 'navigate') {
                        // Poderia retornar uma página de erro offline
                        return new Response('<h1>Você está offline e esta página não está em cache.</h1>', {
                            headers: { 'Content-Type': 'text/html' }
                        });
                    }
                    return new Response(null, { status: 503, statusText: 'Service Unavailable', headers: { 'Content-Type': 'text/plain' } });
                });
            })
        );
        return;
    }

    // Estratégia Network-First com fallback para Cache para a API do Google Apps Script (dados dinâmicos)
    // E para requisições POST (que geralmente modificam dados)
    if (requestUrl.hostname.includes('script.google.com') && requestUrl.pathname.includes('/exec')) {
        event.respondWith(
            fetch(event.request.clone())
                .then(response => {
                    // Quando a rede está disponível, armazena uma cópia da resposta no cache para uso offline
                    // (Apenas para requisições GET ou POSTs que retornam dados que podem ser cacheados)
                    if (response.ok && event.request.method === 'GET') { // Cacheia GETs de dados
                        caches.open(DATA_CACHE_NAME).then(cache => {
                            cache.put(event.request, response.clone());
                        });
                    }
                    return response;
                })
                .catch(async () => {
                    // Se a rede falhar, tenta buscar do cache de dados (apenas para GETs)
                    if (event.request.method === 'GET') {
                        const cachedResponse = await caches.match(event.request);
                        if (cachedResponse) {
                            console.log('[SW] Serving from data cache:', event.request.url);
                            return cachedResponse;
                        }
                    }
                    // Para POSTs offline, a lógica de fila de sincronização é mais adequada no front-end
                    // ou um erro direto se não for um GET.
                    console.warn('[SW] Network request failed and no data in cache for:', event.request.url);
                    return new Response('{"status": "error", "message": "Offline: Falha na requisição de rede ou dados não disponíveis offline."}', { 
                        status: 503, 
                        headers: { 'Content-Type': 'application/json' } 
                    });
                })
        );
        return;
    }

    // Para outras requisições (imagens, etc. que não são Apps Script nem App Shell), use Network-First
    event.respondWith(
        fetch(event.request).catch(() => {
            return caches.match(event.request); // Fallback para cache se rede falhar
        })
    );
});

// Sincronização em segundo plano (requer um pouco mais de configuração no front-end para registrar)
// O front-end (script.js) registra o evento 'sync-pending-operations'
self.addEventListener('sync', event => {
    if (event.tag === 'sync-pending-operations') {
        console.log('[SW] Background sync event triggered: sync-pending-operations');
        event.waitUntil(self.clients.matchAll().then(clients => {
            clients.forEach(client => {
                // Envia uma mensagem para a página principal para iniciar a sincronização
                client.postMessage({ type: 'SYNC_NOW' });
            });
        }));
    }
});

// Listener para mensagens do front-end
self.addEventListener('message', event => {
    if (event.data && event.data.type === 'SKIP_WAITING') {
        self.skipWaiting();
    }
});