// sw.js - Service Worker pour KOMBAR FERD PWA
// Gestion du cache et fonctionnalités hors ligne

const CACHE_NAME = 'kombar-ferd-v1.1.0';
const STATIC_CACHE_NAME = 'kombar-ferd-static-v1.1.0';
const API_CACHE_NAME = 'kombar-ferd-api-v1.1.0';
const OFFLINE_QUEUE_CACHE = 'kombar-ferd-offline-queue-v1.0.0';

// Ressources à mettre en cache immédiatement
const STATIC_ASSETS = [
    './index.html',
    './styles.css', 
    './responsive.css',
    './apiClient.js',
    './manifest.json',
    './icons/icon-192x192.png',
    './icons/icon-512x512.png',
    './performance.js',
    './charts-fournisseur.js',
    './pdf-export-enhanced.js',
    // Chart.js sera chargé à la demande maintenant
    'https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js',
    'https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js',
    'https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js'
];

// Ressources API à mettre en cache
const API_ENDPOINTS = [
    './auth.php',
    './pesees.php?action=stats',
    './pesees.php?action=options'
];

// Installation du Service Worker
self.addEventListener('install', event => {
    console.log('🔧 Service Worker: Installation');
    
    event.waitUntil(
        Promise.all([
            // Cache des ressources statiques
            caches.open(STATIC_CACHE_NAME).then(cache => {
                console.log('💾 Cache: Mise en cache des ressources statiques');
                return cache.addAll(STATIC_ASSETS.map(url => new Request(url, {
                    cache: 'reload' // Force le téléchargement
                })));
            }),
            
            // Pré-cache des données API importantes
            caches.open(API_CACHE_NAME).then(cache => {
                console.log('📊 Cache: Pré-chargement des données API');
                return Promise.allSettled(
                    API_ENDPOINTS.map(url => 
                        fetch(url).then(response => {
                            if (response.ok) {
                                return cache.put(url, response.clone());
                            }
                        }).catch(err => {
                            console.warn(`⚠️ Impossible de pré-charger: ${url}`, err);
                        })
                    )
                );
            })
        ]).then(() => {
            console.log('✅ Service Worker: Installation terminée');
            // Forcer l'activation immédiate
            return self.skipWaiting();
        })
    );
});

// Activation du Service Worker
self.addEventListener('activate', event => {
    console.log('🚀 Service Worker: Activation');
    
    event.waitUntil(
        Promise.all([
            // Nettoyer les anciens caches
            caches.keys().then(cacheNames => {
                const validCaches = [STATIC_CACHE_NAME, API_CACHE_NAME, CACHE_NAME];
                return Promise.all(
                    cacheNames.map(cacheName => {
                        if (!validCaches.includes(cacheName)) {
                            console.log(`🧹 Cache: Suppression ancien cache ${cacheName}`);
                            return caches.delete(cacheName);
                        }
                    })
                );
            }),
            
            // Prendre contrôle immédiatement
            self.clients.claim()
        ]).then(() => {
            console.log('✅ Service Worker: Activation terminée');
            
            // Notifier l'app principale
            self.clients.matchAll().then(clients => {
                clients.forEach(client => {
                    client.postMessage({
                        type: 'SW_ACTIVATED',
                        message: 'Service Worker activé - Mode hors ligne disponible!'
                    });
                });
            });
        })
    );
});

// Interception des requêtes réseau
self.addEventListener('fetch', event => {
    const request = event.request;
    const url = new URL(request.url);
    
    // Ignorer les extensions de navigateur
    if (url.protocol.startsWith('chrome-extension')) {
        return;
    }
    
    // Gestion spéciale des requêtes POST/PUT/DELETE (mutations)
    if (['POST', 'PUT', 'DELETE'].includes(request.method)) {
        event.respondWith(
            fetch(request.clone()).catch(async () => {
                // Si échec réseau et que c'est une mutation, mettre en queue
                if (isAPIRequest(request)) {
                    const body = await request.clone().text();
                    await addToOfflineQueue(request, { body });
                    
                    return new Response(JSON.stringify({
                        success: false,
                        queued: true,
                        message: 'Requête mise en queue pour synchronisation ultérieure'
                    }), {
                        status: 202,
                        headers: { 'Content-Type': 'application/json' }
                    });
                }
                throw error;
            })
        );
        return;
    }
    
    // Requêtes GET: Stratégie selon le type de ressource
    if (isStaticAsset(request)) {
        // Ressources statiques: Cache first
        event.respondWith(cacheFirstStrategy(request, STATIC_CACHE_NAME));
    } else if (isAPIRequest(request)) {
        // API: Network first avec fallback cache (sauf auth)
        event.respondWith(networkFirstStrategy(request, API_CACHE_NAME));
    } else {
        // Autres: Network first
        event.respondWith(networkFirstStrategy(request, CACHE_NAME));
    }
});

// Vérifier si c'est une ressource statique
function isStaticAsset(request) {
    const url = request.url;
    return (
        url.includes('.html') ||
        url.includes('.css') ||
        url.includes('.js') ||
        url.includes('.png') ||
        url.includes('.jpg') ||
        url.includes('.svg') ||
        url.includes('chart.min.js')
    );
}

// Vérifier si c'est une requête API
function isAPIRequest(request) {
    const url = new URL(request.url);
    return (
        url.pathname.includes('/auth.php') ||
        url.pathname.includes('/pesees.php') ||
        url.pathname.includes('/combo_data.php') ||
        url.pathname.includes('/get_ticket.php') ||
        url.pathname.includes('/ticket.php')
    );
}

// Vérifier si c'est une requête d'authentification
function isAuthRequest(request) {
    const url = new URL(request.url);
    return url.pathname.includes('/auth.php');
}

// Stratégie Cache First (pour ressources statiques)
async function cacheFirstStrategy(request, cacheName) {
    try {
        // Chercher dans le cache d'abord
        const cachedResponse = await caches.match(request);
        if (cachedResponse) {
            console.log(`💾 Cache hit: ${request.url}`);
            return cachedResponse;
        }
        
        // Si pas en cache, récupérer du réseau
        console.log(`🌐 Network fetch: ${request.url}`);
        const networkResponse = await fetch(request);
        
        // Mettre en cache si succès
        if (networkResponse.ok) {
            const cache = await caches.open(cacheName);
            cache.put(request, networkResponse.clone());
        }
        
        return networkResponse;
        
    } catch (error) {
        console.error(`❌ Erreur cache-first pour ${request.url}:`, error);
        
        // Fallback: page hors ligne pour HTML
        if (request.destination === 'document') {
            return createOfflinePage();
        }
        
        throw error;
    }
}

// Stratégie Network First (pour API et contenu dynamique)
async function networkFirstStrategy(request, cacheName) {
    try {
        // Essayer le réseau d'abord
        console.log(`🌐 Network first: ${request.url}`);
        const networkResponse = await fetch(request);
        
        // Mettre en cache si succès ET ce n'est pas une requête d'auth échouée
        if (networkResponse.ok && !isAuthRequest(request)) {
            const cache = await caches.open(cacheName);
            // Cloner la réponse car elle ne peut être lue qu'une fois
            cache.put(request, networkResponse.clone());
        }
        
        return networkResponse;
        
    } catch (error) {
        console.warn(`⚠️ Network failed pour ${request.url}, tentative cache:`, error);
        
        // Fallback: chercher dans le cache
        const cachedResponse = await caches.match(request);
        if (cachedResponse) {
            console.log(`💾 Cache fallback: ${request.url}`);
            
            // Ajouter un header pour indiquer que c'est du cache
            const response = cachedResponse.clone();
            response.headers.set('X-Served-By', 'ServiceWorker-Cache');
            return response;
        }
        
        // Si c'est une requête API, retourner une réponse d'erreur JSON
        if (isAPIRequest(request)) {
            return new Response(JSON.stringify({
                success: false,
                error: true,
                message: 'Mode hors ligne - Données non disponibles',
                offline: true,
                timestamp: new Date().toISOString()
            }), {
                status: 200, // 200 pour éviter les erreurs côté client
                statusText: 'Offline Mode',
                headers: {
                    'Content-Type': 'application/json',
                    'X-Served-By': 'ServiceWorker-Offline'
                }
            });
        }
        
        throw error;
    }
}

// Créer une page hors ligne
function createOfflinePage() {
    const offlineHTML = `
        <!DOCTYPE html>
        <html lang="fr">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>KOMBAR FERD - Hors ligne</title>
            <style>
                body {
                    font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
                    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                    color: white;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    min-height: 100vh;
                    margin: 0;
                    text-align: center;
                }
                .offline-container {
                    background: rgba(255, 255, 255, 0.1);
                    backdrop-filter: blur(20px);
                    border-radius: 20px;
                    padding: 40px;
                    box-shadow: 0 25px 50px rgba(0, 0, 0, 0.3);
                }
                .icon { font-size: 4rem; margin-bottom: 20px; }
                h1 { font-size: 2rem; margin-bottom: 15px; }
                p { font-size: 1.1rem; opacity: 0.9; margin-bottom: 25px; }
                button {
                    background: rgba(255, 255, 255, 0.2);
                    border: 1px solid rgba(255, 255, 255, 0.3);
                    color: white;
                    padding: 12px 24px;
                    border-radius: 25px;
                    cursor: pointer;
                    font-size: 1rem;
                    transition: all 0.3s ease;
                }
                button:hover {
                    background: rgba(255, 255, 255, 0.3);
                    transform: translateY(-2px);
                }
            </style>
        </head>
        <body>
            <div class="offline-container">
                <div class="icon">📶❌</div>
                <h1>Mode Hors Ligne</h1>
                <p>Vous êtes actuellement hors ligne.<br>
                   Certaines fonctionnalités peuvent être limitées.</p>
                <button onclick="window.location.reload()">
                    🔄 Réessayer la connexion
                </button>
            </div>
        </body>
        </html>
    `;
    
    return new Response(offlineHTML, {
        status: 200,
        headers: {
            'Content-Type': 'text/html',
            'X-Served-By': 'ServiceWorker-Offline'
        }
    });
}

// Gestion des messages de l'app principale
self.addEventListener('message', event => {
    console.log('💬 Message reçu:', event.data);
    
    switch (event.data.type) {
        case 'SKIP_WAITING':
            // Forcer la mise à jour du Service Worker
            self.skipWaiting();
            break;
            
        case 'GET_VERSION':
            // Retourner la version du cache
            event.ports[0].postMessage({
                version: CACHE_NAME,
                static: STATIC_CACHE_NAME,
                api: API_CACHE_NAME
            });
            break;
            
        case 'CLEAR_CACHE':
            // Nettoyer tous les caches
            caches.keys().then(cacheNames => {
                Promise.all(cacheNames.map(name => caches.delete(name)))
                    .then(() => {
                        event.ports[0].postMessage({ success: true });
                    });
            });
            break;
    }
});

// Gestion des notifications push (préparation)
self.addEventListener('push', event => {
    console.log('🔔 Notification push reçue:', event);
    
    if (event.data) {
        const data = event.data.json();
        const options = {
            body: data.body || 'Nouvelle notification KOMBAR FERD',
            icon: './icons/icon-192x192.png',
            badge: './icons/icon-96x96.png',
            tag: data.tag || 'kombar-notification',
            requireInteraction: data.requireInteraction || false,
            actions: data.actions || []
        };
        
        event.waitUntil(
            self.registration.showNotification(data.title || 'KOMBAR FERD', options)
        );
    }
});

// Gestion des clics sur notifications
self.addEventListener('notificationclick', event => {
    console.log('🔔 Clic sur notification:', event);
    
    event.notification.close();
    
    // Ouvrir ou focaliser l'app
    event.waitUntil(
        self.clients.matchAll({ type: 'window' }).then(clients => {
            // Si l'app est déjà ouverte, la focaliser
            for (const client of clients) {
                if (client.url.includes('pesee_webapp.html') && 'focus' in client) {
                    return client.focus();
                }
            }
            
            // Sinon, ouvrir une nouvelle fenêtre
            if (self.clients.openWindow) {
                return self.clients.openWindow('./index.html');
            }
        })
    );
});

// ===== FONCTIONNALITÉS AVANCÉES PWA =====

// Queue hors-ligne pour les requêtes échouées
let offlineQueue = [];

// Synchronisation en arrière-plan
self.addEventListener('sync', event => {
    console.log('🔄 Background sync:', event.tag);
    
    if (event.tag === 'offline-sync') {
        event.waitUntil(processOfflineQueue());
    }
});

// Traiter la queue hors-ligne
async function processOfflineQueue() {
    console.log('📤 Traitement de la queue hors-ligne...');
    
    try {
        const cache = await caches.open(OFFLINE_QUEUE_CACHE);
        const requests = await cache.keys();
        
        for (const request of requests) {
            try {
                // Récupérer les données de la queue
                const cachedResponse = await cache.match(request);
                if (cachedResponse) {
                    const data = await cachedResponse.json();
                    
                    // Tenter d'envoyer la requête
                    const response = await fetch(request.url, {
                        method: request.method,
                        headers: data.headers,
                        body: data.body
                    });
                    
                    if (response.ok) {
                        // Succès - supprimer de la queue
                        await cache.delete(request);
                        console.log('✅ Requête synchronisée:', request.url);
                        
                        // Notifier l'app
                        notifyClientsOfSync(request.url, true);
                    }
                }
            } catch (error) {
                console.warn('⚠️ Échec synchronisation:', request.url, error);
            }
        }
    } catch (error) {
        console.error('❌ Erreur traitement queue:', error);
    }
}

// Ajouter une requête à la queue hors-ligne
async function addToOfflineQueue(request, data) {
    try {
        const cache = await caches.open(OFFLINE_QUEUE_CACHE);
        const queueData = {
            url: request.url,
            method: request.method,
            headers: [...request.headers.entries()],
            body: data.body,
            timestamp: Date.now()
        };
        
        await cache.put(request, new Response(JSON.stringify(queueData)));
        console.log('📥 Ajouté à la queue hors-ligne:', request.url);
        
        // Programmer une sync
        if ('serviceWorker' in navigator && 'sync' in window.ServiceWorkerRegistration.prototype) {
            self.registration.sync.register('offline-sync');
        }
    } catch (error) {
        console.error('❌ Erreur ajout queue:', error);
    }
}

// Notifier les clients de la synchronisation
function notifyClientsOfSync(url, success) {
    self.clients.matchAll().then(clients => {
        clients.forEach(client => {
            client.postMessage({
                type: 'SYNC_RESULT',
                url: url,
                success: success
            });
        });
    });
}

// Détecteur de connectivité réseau
let isOnline = true;

self.addEventListener('online', () => {
    console.log('🌐 Connexion rétablie');
    isOnline = true;
    
    // Notifier l'app
    self.clients.matchAll().then(clients => {
        clients.forEach(client => {
            client.postMessage({
                type: 'NETWORK_STATUS',
                online: true
            });
        });
    });
    
    // Traiter la queue automatiquement
    processOfflineQueue();
});

self.addEventListener('offline', () => {
    console.log('📡 Connexion perdue');
    isOnline = false;
    
    // Notifier l'app
    self.clients.matchAll().then(clients => {
        clients.forEach(client => {
            client.postMessage({
                type: 'NETWORK_STATUS', 
                online: false
            });
        });
    });
});

// Note: La gestion des fetch est déjà faite au-dessus dans le listener principal

console.log('📋 Service Worker KOMBAR FERD initialisé avec fonctionnalités avancées');