/**
 * Service Worker - PocketBooking Pro PWA
 * 
 * Strategie: Network First mit Cache-Fallback
 * - Versucht immer zuerst das Netzwerk
 * - Fällt auf Cache zurück bei Offline
 * - Cached statische Assets aggressiver (Stale-While-Revalidate)
 * - Unterstützt mehrsprachige Push-Benachrichtigungen
 * - Speichert Sprache persistent in IndexedDB
 * 
 * Push-Notifications:
 * - Badge (links, klein, monochrom): notification-icon_pwa_mrtr.png
 * - Icon (rechts, groß, vollfarbig): Dynamisch generiertes Plus-Symbol
 *
 * @package SimpleBookingCalendar
 * @since 1.2.0
 * @updated 2.2.0 - IndexedDB für persistente Sprach-Speicherung
 */

const CACHE_NAME = 'simpbook-pwa-v4';
const CACHE_VERSION = 4;
const DB_NAME = 'simpbook-pwa-settings';
const DB_VERSION = 1;
const STORE_NAME = 'settings';

// Aktuelle Plugin-Sprache (Fallback, wird aus IndexedDB überschrieben)
let currentLanguage = 'de_DE';

/**
 * Öffnet die IndexedDB Datenbank
 */
function openDatabase() {
    return new Promise((resolve, reject) => {
        const request = indexedDB.open(DB_NAME, DB_VERSION);
        
        request.onerror = () => {
            reject(request.error);
        };
        
        request.onsuccess = () => {
            resolve(request.result);
        };
        
        request.onupgradeneeded = (event) => {
            const db = event.target.result;
            if (!db.objectStoreNames.contains(STORE_NAME)) {
                db.createObjectStore(STORE_NAME, { keyPath: 'key' });
            }
        };
    });
}

/**
 * Speichert die Sprache in IndexedDB (persistent!)
 */
async function saveLanguageToDB(language) {
    try {
        const db = await openDatabase();
        const transaction = db.transaction(STORE_NAME, 'readwrite');
        const store = transaction.objectStore(STORE_NAME);
        
        store.put({ key: 'language', value: language });
        
        return new Promise((resolve, reject) => {
            transaction.oncomplete = () => {
                currentLanguage = language;
                console.log('[Simpbook SW] Language saved to IndexedDB:', language);
                resolve();
            };
            transaction.onerror = () => {
                reject(transaction.error);
            };
        });
    } catch (error) {
        console.warn('[Simpbook SW] Could not save to IndexedDB:', error);
        currentLanguage = language;
    }
}

/**
 * Lädt die Sprache aus IndexedDB
 */
async function loadLanguageFromDB() {
    try {
        const db = await openDatabase();
        const transaction = db.transaction(STORE_NAME, 'readonly');
        const store = transaction.objectStore(STORE_NAME);
        const request = store.get('language');
        
        return new Promise((resolve) => {
            request.onsuccess = () => {
                if (request.result && request.result.value) {
                    currentLanguage = request.result.value;
                    console.log('[Simpbook SW] Language loaded from IndexedDB:', currentLanguage);
                }
                resolve(currentLanguage);
            };
            request.onerror = () => {
                console.log('[Simpbook SW] Could not load language from IndexedDB');
                resolve(currentLanguage);
            };
        });
    } catch (error) {
        console.warn('[Simpbook SW] IndexedDB error:', error);
        return currentLanguage;
    }
}

// Hart kodierte Übersetzungen für Push-Benachrichtigungen
const PUSH_TRANSLATIONS = {
    'push_new_booking_title': {
        'de_DE': 'Neue Buchung',
        'en_US': 'New Booking',
        'en_GB': 'New Booking',
        'en_US_AMPM': 'New Booking',
        'it_IT': 'Nuova Prenotazione',
        'es_ES': 'Nueva Reserva',
        'fr_FR': 'Nouvelle Réservation',
        'pl_PL': 'Nowa Rezerwacja',
        'ru_RU': 'Новое бронирование',
        'sv_SE': 'Ny bokning'
    },
    'push_new_booking_body': {
        'de_DE': 'Eine neue Buchung ist eingegangen.',
        'en_US': 'A new booking has been received.',
        'en_GB': 'A new booking has been received.',
        'en_US_AMPM': 'A new booking has been received.',
        'it_IT': 'È arrivata una nuova prenotazione.',
        'es_ES': 'Se ha recibido una nueva reserva.',
        'fr_FR': 'Une nouvelle réservation a été reçue.',
        'pl_PL': 'Otrzymano nową rezerwację.',
        'ru_RU': 'Получено новое бронирование.',
        'sv_SE': 'En ny bokning har mottagits.'
    },
    'push_test_title': {
        'de_DE': 'Test-Benachrichtigung',
        'en_US': 'Test Notification',
        'en_GB': 'Test Notification',
        'en_US_AMPM': 'Test Notification',
        'it_IT': 'Notifica di Test',
        'es_ES': 'Notificación de Prueba',
        'fr_FR': 'Notification de Test',
        'pl_PL': 'Powiadomienie Testowe',
        'ru_RU': 'Тестовое уведомление',
        'sv_SE': 'Testnotifiering'
    },
    'push_test_body': {
        'de_DE': 'Dies ist eine Test-Nachricht. Funktioniert! ✓',
        'en_US': 'This is a test message. Working! ✓',
        'en_GB': 'This is a test message. Working! ✓',
        'en_US_AMPM': 'This is a test message. Working! ✓',
        'it_IT': 'Questo è un messaggio di test. Funziona! ✓',
        'es_ES': 'Este es un mensaje de prueba. ¡Funciona! ✓',
        'fr_FR': 'Ceci est un message de test. Fonctionne! ✓',
        'pl_PL': 'To jest wiadomość testowa. Działa! ✓',
        'ru_RU': 'Это тестовое сообщение. Работает! ✓',
        'sv_SE': 'Detta är ett testmeddelande. Fungerar! ✓'
    }
};

/**
 * Holt die Übersetzung für einen Key in der aktuellen Sprache
 */
function getPushTranslation(key) {
    if (!PUSH_TRANSLATIONS[key]) {
        return key;
    }
    
    // Normalisiere Sprache für englische Varianten
    let lang = currentLanguage;
    if (lang.startsWith('en_') && !PUSH_TRANSLATIONS[key][lang]) {
        lang = 'en_US';
    }
    
    if (PUSH_TRANSLATIONS[key][lang]) {
        return PUSH_TRANSLATIONS[key][lang];
    }
    
    // Fallback auf Englisch, dann Deutsch
    if (PUSH_TRANSLATIONS[key]['en_US']) {
        return PUSH_TRANSLATIONS[key]['en_US'];
    }
    return PUSH_TRANSLATIONS[key]['de_DE'] || key;
}

// Assets die gecached werden sollen (Patterns)
const CACHEABLE_PATTERNS = [
    /\.css(\?.*)?$/,
    /\.js(\?.*)?$/,
    /\.woff2?(\?.*)?$/,
    /\.ttf(\?.*)?$/,
    /\.png(\?.*)?$/,
    /\.jpg(\?.*)?$/,
    /\.jpeg(\?.*)?$/,
    /\.svg(\?.*)?$/,
    /\.webp(\?.*)?$/
];

// URLs die NICHT gecached werden sollen
const EXCLUDE_PATTERNS = [
    /admin-ajax\.php/,
    /wp-cron\.php/,
    /wp-login\.php/,
    /nonce/,
    /\_wpnonce/,
    /logout/,
    /simpbook-manifest\.json/,
    /simpbook-sw\.js/
];

/**
 * Install Event
 */
self.addEventListener('install', (event) => {
    console.log('[Simpbook SW] Installing Service Worker v' + CACHE_VERSION);
    
    // Skip waiting - sofort aktivieren (keine Assets pre-cachen)
    event.waitUntil(self.skipWaiting());
});

/**
 * Activate Event - Alte Caches aufräumen
 */
self.addEventListener('activate', (event) => {
    console.log('[Simpbook SW] Activating Service Worker v' + CACHE_VERSION);
    
    event.waitUntil(
        caches.keys()
            .then((cacheNames) => {
                return Promise.all(
                    cacheNames
                        .filter((name) => {
                            // Lösche alte Versionen unserer Caches
                            return name.startsWith('simpbook-') && name !== CACHE_NAME;
                        })
                        .map((name) => {
                            console.log('[Simpbook SW] Deleting old cache:', name);
                            return caches.delete(name);
                        })
                );
            })
            .then(() => {
                console.log('[Simpbook SW] Claiming clients');
                return self.clients.claim();
            })
    );
});

/**
 * Fetch Event - Routing der Anfragen
 */
self.addEventListener('fetch', (event) => {
    const request = event.request;
    const url = new URL(request.url);
    
    // Nur GET-Requests behandeln
    if (request.method !== 'GET') {
        return;
    }
    
    // Excluded URLs nicht cachen
    if (EXCLUDE_PATTERNS.some(pattern => pattern.test(url.href))) {
        return;
    }
    
    // Nur Same-Origin Requests
    if (url.origin !== location.origin) {
        return;
    }
    
    // Strategie basierend auf Request-Typ wählen
    const isCacheableAsset = CACHEABLE_PATTERNS.some(pattern => pattern.test(url.pathname));
    
    if (isCacheableAsset) {
        // Statische Assets: Stale-While-Revalidate (sofortige Antwort, Update im Hintergrund)
        event.respondWith(staleWhileRevalidate(request));
    } else if (request.headers.get('accept')?.includes('text/html')) {
        // HTML: Network First mit Offline-Fallback
        event.respondWith(networkFirst(request));
    }
});

/**
 * Network First Strategie
 * Versuche zuerst Netzwerk, dann Cache, dann Offline-Fallback
 */
async function networkFirst(request) {
    try {
        const networkResponse = await fetch(request);
        
        // Nur erfolgreiche Responses cachen
        if (networkResponse.ok) {
            const cache = await caches.open(CACHE_NAME);
            cache.put(request, networkResponse.clone());
        }
        
        return networkResponse;
    } catch (error) {
        console.log('[Simpbook SW] Network failed, trying cache:', request.url);
        
        const cachedResponse = await caches.match(request);
        
        if (cachedResponse) {
            return cachedResponse;
        }
        
        // Offline Fallback Page
        return new Response(
            `<!DOCTYPE html>
            <html lang="de">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>Offline - PocketBooking</title>
                <style>
                    * { box-sizing: border-box; }
                    body {
                        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
                        display: flex;
                        align-items: center;
                        justify-content: center;
                        min-height: 100vh;
                        margin: 0;
                        background: linear-gradient(135deg, #1a4a8a 0%, #0e7490 100%) !important;
                        color: white;
                        text-align: center;
                        padding: 20px;
                    }
                    .offline-container {
                        max-width: 400px;
                    }
                    .offline-icon {
                        font-size: 64px;
                        margin-bottom: 20px;
                    }
                    h1 { margin: 0 0 10px; font-size: 24px; font-weight: 600; }
                    p { margin: 0 0 20px; opacity: 0.9; line-height: 1.5; }
                    button {
                        background: white;
                        color: #667eea;
                        border: none;
                        padding: 14px 28px;
                        border-radius: 8px;
                        font-size: 16px;
                        font-weight: 600;
                        cursor: pointer;
                        transition: transform 0.2s, box-shadow 0.2s;
                    }
                    button:hover {
                        transform: translateY(-2px);
                        box-shadow: 0 4px 12px rgba(0,0,0,0.2);
                    }
                    button:active {
                        transform: translateY(0);
                    }
                </style>
            </head>
            <body>
                <div class="offline-container">
                    <div class="offline-icon">📡</div>
                    <h1>Keine Verbindung</h1>
                    <p>Bitte überprüfen Sie Ihre Internetverbindung und versuchen Sie es erneut.</p>
                    <button onclick="location.reload()">Erneut versuchen</button>
                </div>
            </body>
            </html>`,
            { 
                headers: { 'Content-Type': 'text/html; charset=utf-8' },
                status: 503
            }
        );
    }
}

/**
 * Stale-While-Revalidate Strategie
 * Sofortige Antwort aus Cache, Update im Hintergrund
 */
async function staleWhileRevalidate(request) {
    const cache = await caches.open(CACHE_NAME);
    const cachedResponse = await cache.match(request);
    
    // Netzwerk-Anfrage im Hintergrund
    const fetchPromise = fetch(request)
        .then(async (networkResponse) => {
            if (networkResponse.ok) {
                await cache.put(request, networkResponse.clone());
            }
            return networkResponse;
        })
        .catch(() => null);
    
    // Sofort aus Cache antworten wenn vorhanden, sonst warten auf Netzwerk
    return cachedResponse || fetchPromise;
}

/**
 * Erstellt ein Plus-Icon als Data-URL
 * 
 * Für das RECHTE Icon in Push-Notifications (vollfarbig, größer)
 * ⚠️ Das Badge (links, klein, monochrom) kommt aus notification-icon_pwa.png
 */
function createPlusIconDataUrl() {
    const svg = `
        <svg xmlns="http://www.w3.org/2000/svg" width="192" height="192" viewBox="0 0 192 192">
            <rect width="192" height="192" rx="24" fill="#667eea"/>
            <path d="M96 48v96M48 96h96" stroke="white" stroke-width="16" stroke-linecap="round"/>
        </svg>
    `;
    
    // SVG zu Data-URL konvertieren
    const encoded = btoa(unescape(encodeURIComponent(svg)));
    return 'data:image/svg+xml;base64,' + encoded;
}

/**
 * Push Event - Benachrichtigung anzeigen
 * 
 * ⚠️ WICHTIG: Auch leere Push-Events müssen eine Notification zeigen!
 * Browser terminiert SW wenn keine Notification gezeigt wird.
 * 
 * Icon-Typen in Notifications:
 * - badge (links, klein, monochrom) = notification-icon_pwa.png
 * - icon (rechts, groß, vollfarbig) = Plus-Symbol (dynamisch) oder custom
 */
self.addEventListener('push', async (event) => {
    console.log('[Simpbook SW] ✓ Push event received');
    
    // ⭐ Lade aktuelle Sprache aus IndexedDB
    await loadLanguageFromDB();
    
    let data = {};
    
    // Push-Daten parsen
    if (event.data) {
        try {
            data = event.data.json();
            console.log('[Simpbook SW] Push data:', data);
        } catch (e) {
            // Fallback: Text als Body verwenden
            data = { body: event.data.text() };
            console.log('[Simpbook SW] Push text:', data.body);
        }
    }
    
    // Prüfe ob Test-Push
    const isTestPush = data.body && (data.body.toLowerCase().includes('test') || data.title?.toLowerCase().includes('test'));
    
    // Titel und Body in aktueller Sprache
    let title, body;
    if (isTestPush) {
        title = data.title || getPushTranslation('push_test_title');
        body = data.body || getPushTranslation('push_test_body');
    } else {
        title = data.title || getPushTranslation('push_new_booking_title');
        body = data.body || getPushTranslation('push_new_booking_body');
    }
    
    // ⭐ Badge: Für Android Statusbar - MUSS weiß auf transparent sein!
    // Android ignoriert alle nicht-weißen Pixel komplett
    const badge = '/wp-content/plugins/simple-appointment-booking/templates/notification-badge-test.png';
    
    // ⭐ Icon: Rechts, groß, vollfarbig
    // Entweder custom Icon aus Push-Data oder dynamisches Plus-Symbol
    const icon = data.icon || createPlusIconDataUrl();
    
    const options = {
        body: body,
        icon: icon,           // Rechts, groß, vollfarbig
        badge: badge,         // Links, klein, monochrom
        vibrate: [200, 100, 200],
        tag: data.tag || 'simpbook-notification',
        renotify: true,
        requireInteraction: false,
        data: {
            url: data.url || '/wp-admin/admin.php?page=simpbook-reservierungen&pwa=1',
            timestamp: Date.now()
        }
    };
    
    // Optionale Actions
    if (data.actions && Array.isArray(data.actions)) {
        options.actions = data.actions;
    }
    
    event.waitUntil(
        self.registration.showNotification(title, options)
    );
});

/**
 * Notification Click Event
 */
self.addEventListener('notificationclick', (event) => {
    console.log('[Simpbook SW] Notification clicked');
    
    event.notification.close();
    
    // URL aus Notification-Daten oder Default
    const url = event.notification.data?.url || '/wp-admin/admin.php?page=simpbook-reservierungen&pwa=1';
    
    event.waitUntil(
        clients.matchAll({ type: 'window', includeUncontrolled: true })
            .then((clientList) => {
                // Prüfe ob bereits ein Fenster offen ist
                for (const client of clientList) {
                    // Wenn die URL bereits offen ist, fokussiere das Fenster
                    if (client.url.includes('simpbook') && 'focus' in client) {
                        return client.focus().then((focusedClient) => {
                            // Navigiere zur neuen URL
                            if (focusedClient && 'navigate' in focusedClient) {
                                return focusedClient.navigate(url);
                            }
                        });
                    }
                }
                // Sonst neues Fenster öffnen
                return clients.openWindow(url);
            })
    );
});

/**
 * Notification Close Event (optional)
 */
self.addEventListener('notificationclose', (event) => {
    console.log('[Simpbook SW] Notification closed');
});

/**
 * Message Event - Kommunikation mit der Seite
 */
self.addEventListener('message', (event) => {
    console.log('[Simpbook SW] Message received:', event.data);
    
    // Skip Waiting - sofort neuen SW aktivieren
    if (event.data && event.data.type === 'SKIP_WAITING') {
        console.log('[Simpbook SW] Skip waiting requested');
        self.skipWaiting();
    }
    
    // ⭐ Sprache setzen (wird in IndexedDB persistent gespeichert!)
    if (event.data && event.data.type === 'SET_LANGUAGE') {
        const newLanguage = event.data.language || 'de_DE';
        console.log('[Simpbook SW] Setting language to:', newLanguage);
        saveLanguageToDB(newLanguage).catch(() => {
            currentLanguage = newLanguage;
        });
    }
    
    // Cache leeren
    if (event.data && event.data.type === 'CLEAR_CACHE') {
        console.log('[Simpbook SW] Clear cache requested');
        event.waitUntil(
            caches.keys().then((cacheNames) => {
                return Promise.all(
                    cacheNames
                        .filter(name => name.startsWith('simpbook-'))
                        .map(name => {
                            console.log('[Simpbook SW] Deleting cache:', name);
                            return caches.delete(name);
                        })
                );
            })
        );
    }
    
    // Cache-Info abrufen
    if (event.data && event.data.type === 'GET_CACHE_INFO') {
        event.waitUntil(
            caches.open(CACHE_NAME).then(async (cache) => {
                const keys = await cache.keys();
                const info = {
                    name: CACHE_NAME,
                    version: CACHE_VERSION,
                    entries: keys.length
                };
                
                // Antwort an Client senden
                event.source.postMessage({
                    type: 'CACHE_INFO',
                    data: info
                });
            })
        );
    }
});

// Log beim Laden
console.log('[Simpbook SW] Service Worker loaded - v' + CACHE_VERSION);
