/**
 * MYP Platform Service Worker
 * Offline-First Caching Strategy
 */

// MYP Platform Service Worker
const CACHE_NAME = 'myp-platform-cache-v1';
const STATIC_CACHE = 'myp-static-v1';
const DYNAMIC_CACHE = 'myp-dynamic-v1';

const ASSETS_TO_CACHE = [
  '/',
  '/dashboard',
  '/static/css/tailwind.min.css',
  '/static/css/tailwind-dark.min.css',
  '/static/js/ui-components.js',
  '/static/js/offline-app.js',
  '/static/icons/mercedes-logo.svg',
  '/static/icons/icon-144x144.png',
  '/static/favicon.ico'
];

// Static files patterns
const STATIC_PATTERNS = [
  /\.css$/,
  /\.js$/,
  /\.svg$/,
  /\.png$/,
  /\.ico$/,
  /\.woff2?$/
];

// API request patterns to avoid caching
const API_PATTERNS = [
  /^\/api\//,
  /^\/auth\//,
  /^\/api\/jobs/,
  /^\/api\/printers/,
  /^\/api\/stats/
];

// Install event - cache core assets
self.addEventListener('install', (event) => {
  console.log('Service Worker: Installing...');
  
  event.waitUntil(
    caches.open(STATIC_CACHE)
      .then((cache) => {
        console.log('Service Worker: Caching static files');
        return cache.addAll(ASSETS_TO_CACHE);
      })
      .then(() => {
        console.log('Service Worker: Static files cached');
        return self.skipWaiting();
      })
      .catch((error) => {
        console.error('Service Worker: Error caching static files', error);
      })
  );
});

// Activate event - clean up old caches
self.addEventListener('activate', (event) => {
  console.log('Service Worker: Activating...');
  
  event.waitUntil(
    caches.keys()
      .then((cacheNames) => {
        return Promise.all(
          cacheNames.map((cacheName) => {
            if (cacheName !== STATIC_CACHE && cacheName !== DYNAMIC_CACHE) {
              console.log('Service Worker: Deleting old cache', cacheName);
              return caches.delete(cacheName);
            }
          })
        );
      })
      .then(() => {
        console.log('Service Worker: Activated');
        return self.clients.claim();
      })
  );
});

// Fetch event - handle requests
self.addEventListener('fetch', (event) => {
  const { request } = event;
  const url = new URL(request.url);
  
  // Unterstütze sowohl HTTP als auch HTTPS
  if (request.method !== 'GET' || 
      (url.protocol !== 'http:' && url.protocol !== 'https:')) {
    return;
  }
  
  // Simple network-first approach
  event.respondWith(
    fetch(request)
      .then((response) => {
        // Cache successful static responses
        if (response && response.status === 200 && isStaticFile(url.pathname) &&
            (url.protocol === 'http:' || url.protocol === 'https:')) {
          const responseClone = response.clone();
          caches.open(STATIC_CACHE).then((cache) => {
            cache.put(request, responseClone);
          }).catch(err => {
            console.warn('Failed to cache response:', err);
          });
        }
        return response;
      })
      .catch(() => {
        // Fallback to cache if network fails
        return caches.match(request);
      })
  );
});

// Check if request is for a static file
function isStaticFile(pathname) {
  return STATIC_PATTERNS.some(pattern => pattern.test(pathname));
}

// Check if request is an API request
function isAPIRequest(pathname) {
  return API_PATTERNS.some(pattern => pattern.test(pathname));
}

// Check if request is for a page
function isPageRequest(request) {
  return request.mode === 'navigate';
}

// MYP Platform Service Worker
const STATIC_FILES = [
    '/',
    '/static/css/tailwind.min.css',
    '/static/css/tailwind-dark.min.css',
    '/static/js/ui-components.js',
    '/static/js/offline-app.js',
    '/login',
    '/dashboard'
];

// API endpoints to cache
const API_CACHE_PATTERNS = [
    /^\/api\/dashboard/,
    /^\/api\/printers/,
    /^\/api\/jobs/,
    /^\/api\/stats/
];

// Handle static file requests - Cache First strategy
async function handleStaticFile(request) {
    try {
        const cachedResponse = await caches.match(request);
        if (cachedResponse) {
            return cachedResponse;
        }
        
        const networkResponse = await fetch(request);
        
        // Cache successful responses
        if (networkResponse.ok) {
            const cache = await caches.open(STATIC_CACHE);
            cache.put(request, networkResponse.clone());
        }
        
        return networkResponse;
    } catch (error) {
        console.error('Service Worker: Error handling static file', error);
        
        // Return cached version if available
        const cachedResponse = await caches.match(request);
        if (cachedResponse) {
            return cachedResponse;
        }
        
        // Return offline fallback
        return new Response('Offline - Datei nicht verfügbar', {
            status: 503,
            statusText: 'Service Unavailable'
        });
    }
}

// Handle API requests - Network First with cache fallback
async function handleAPIRequest(request) {
    const url = new URL(request.url);
    
    // Skip caching for chrome-extension URLs
    if (url.protocol === 'chrome-extension:') {
        try {
            return await fetch(request);
        } catch (error) {
            console.error('Failed to fetch from chrome-extension:', error);
            return new Response(JSON.stringify({
                error: 'Fehler beim Zugriff auf chrome-extension',
                offline: true
            }), {
                status: 400,
                headers: { 'Content-Type': 'application/json' }
            });
        }
    }
    
    try {
        // Try network first
        const networkResponse = await fetch(request);
        
        if (networkResponse.ok) {
            // Cache successful GET responses for specific endpoints
            if (request.method === 'GET' && shouldCacheAPIResponse(url.pathname)) {
                const cache = await caches.open(DYNAMIC_CACHE);
                cache.put(request, networkResponse.clone());
            }
            
            return networkResponse;
        }
        
        throw new Error(`HTTP ${networkResponse.status}`);
    } catch (error) {
        console.log('Service Worker: Network failed for API request, trying cache');
        
        // Try cache fallback for GET requests
        const cachedResponse = await caches.match(request);
        if (cachedResponse) {
            // Add offline header to indicate cached response
            const response = cachedResponse.clone();
            response.headers.set('X-Served-By', 'ServiceWorker-Cache');
            return response;
        }
        
        // Return offline response
        return new Response(JSON.stringify({
            error: 'Offline - Daten nicht verfügbar',
            offline: true,
            timestamp: new Date().toISOString()
        }), {
            status: 503,
            statusText: 'Service Unavailable',
            headers: {
                'Content-Type': 'application/json',
                'X-Served-By': 'ServiceWorker-Offline'
            }
        });
    }
}

// Handle page requests - Network First with offline fallback
async function handlePageRequest(request) {
    try {
        const networkResponse = await fetch(request);
        
        if (networkResponse.ok) {
            // Cache successful page responses
            const cache = await caches.open(DYNAMIC_CACHE);
            cache.put(request, networkResponse.clone());
            return networkResponse;
        }
        
        throw new Error(`HTTP ${networkResponse.status}`);
    } catch (error) {
        console.log('Service Worker: Network failed for page request, trying cache');
        
        // Try cache fallback
        const cachedResponse = await caches.match(request);
        if (cachedResponse) {
            return cachedResponse;
        }
        
        // Fallback offline response
        return caches.match('/offline.html') || new Response(
            '<html><body><h1>Offline</h1><p>Sie sind momentan offline. Bitte überprüfen Sie Ihre Internetverbindung.</p></body></html>', 
            {
                status: 200,
                headers: { 'Content-Type': 'text/html' }
            }
        );
    }
}

// Check if API response should be cached
function shouldCacheAPIResponse(pathname) {
    return API_CACHE_PATTERNS.some(pattern => pattern.test(pathname));
}

// Background sync for offline actions
self.addEventListener('sync', (event) => {
    console.log('Service Worker: Background sync triggered', event.tag);
    
    if (event.tag === 'background-sync') {
        event.waitUntil(doBackgroundSync());
    }
});

// Perform background sync
async function doBackgroundSync() {
    try {
        // Get pending requests from IndexedDB or localStorage
        const pendingRequests = await getPendingRequests();
        
        for (const request of pendingRequests) {
            try {
                await fetch(request.url, request.options);
                await removePendingRequest(request.id);
                console.log('Service Worker: Synced request', request.url);
            } catch (error) {
                console.error('Service Worker: Failed to sync request', request.url, error);
            }
        }
    } catch (error) {
        console.error('Service Worker: Background sync failed', error);
    }
}

// Get pending requests (placeholder - implement with IndexedDB)
async function getPendingRequests() {
    // This would typically use IndexedDB to store pending requests
    // For now, return empty array
    return [];
}

// Remove pending request (placeholder - implement with IndexedDB)
async function removePendingRequest(id) {
    // This would typically remove the request from IndexedDB
    console.log('Service Worker: Removing pending request', id);
}

// Push notification handling
self.addEventListener('push', (event) => {
    console.log('Service Worker: Push notification received');
    
    const options = {
        body: 'Sie haben neue Benachrichtigungen',
        icon: '/static/icons/icon-192x192.png',
        badge: '/static/icons/badge-72x72.png',
        vibrate: [100, 50, 100],
        data: {
            dateOfArrival: Date.now(),
            primaryKey: 1
        },
        actions: [
            {
                action: 'explore',
                title: 'Anzeigen',
                icon: '/static/icons/checkmark.png'
            },
            {
                action: 'close',
                title: 'Schließen',
                icon: '/static/icons/xmark.png'
            }
        ]
    };
    
    event.waitUntil(
        self.registration.showNotification('MYP Platform', options)
    );
});

// Notification click handling
self.addEventListener('notificationclick', (event) => {
    console.log('Service Worker: Notification clicked');
    
    event.notification.close();
    
    if (event.action === 'explore') {
        event.waitUntil(
            clients.openWindow('/dashboard')
        );
    }
});

// Message handling from main thread
self.addEventListener('message', (event) => {
    console.log('Service Worker: Message received', event.data);
    
    if (event.data && event.data.type === 'SKIP_WAITING') {
        self.skipWaiting();
    }
    
    if (event.data && event.data.type === 'CACHE_URLS') {
        event.waitUntil(
            cacheUrls(event.data.urls)
        );
    }
});

// Cache specific URLs
async function cacheUrls(urls) {
    try {
        const cache = await caches.open(DYNAMIC_CACHE);
        await cache.addAll(urls);
        console.log('Service Worker: URLs cached', urls);
    } catch (error) {
        console.error('Service Worker: Error caching URLs', error);
    }
}

// Periodic background sync (if supported)
self.addEventListener('periodicsync', (event) => {
    console.log('Service Worker: Periodic sync triggered', event.tag);
    
    if (event.tag === 'content-sync') {
        event.waitUntil(syncContent());
    }
});

// Sync content periodically
async function syncContent() {
    try {
        // Sync critical data in background
        const endpoints = ['/api/dashboard', '/api/jobs'];
        
        for (const endpoint of endpoints) {
            try {
                const response = await fetch(endpoint);
                if (response.ok) {
                    const cache = await caches.open(DYNAMIC_CACHE);
                    cache.put(endpoint, response.clone());
                }
            } catch (error) {
                console.error('Service Worker: Error syncing', endpoint, error);
            }
        }
    } catch (error) {
        console.error('Service Worker: Content sync failed', error);
    }
}

console.log('Service Worker: Script loaded'); 