// EasyStream Service Worker - Enhanced PWA v2.0
const CACHE_VERSION = 'es-v2';
const STATIC_CACHE = `${CACHE_VERSION}-static`;
const IMAGE_CACHE = `${CACHE_VERSION}-images`;
const FONT_CACHE = `${CACHE_VERSION}-fonts`;
const VIDEO_CACHE = `${CACHE_VERSION}-video`;

// Assets to precache
const PRECACHE = [
  '/index.js',
  '/manifest.json',
  '/f_scripts/shared/design-system.css',
  '/f_scripts/shared/accessibility.css',
  '/f_scripts/shared/responsive.css',
  '/f_scripts/shared/themes.css'
];

// Cache size limits
const CACHE_LIMITS = {
  images: 50,
  fonts: 20,
  video: 5
};

// Install event - precache critical assets
self.addEventListener('install', (event) => {
  console.log('[SW] Installing service worker v2.0...');
  event.waitUntil((async () => {
    try {
      const cache = await caches.open(STATIC_CACHE);
      await cache.addAll(PRECACHE);
      console.log('[SW] Precached static assets');
      self.skipWaiting();
    } catch (error) {
      console.error('[SW] Install failed:', error);
    }
  })());
});

// Activate event - clean up old caches
self.addEventListener('activate', (event) => {
  console.log('[SW] Activating service worker v2.0...');
  event.waitUntil((async () => {
    const keys = await caches.keys();
    await Promise.all(
      keys
        .filter(k => !k.startsWith(CACHE_VERSION))
        .map(k => {
          console.log('[SW] Deleting old cache:', k);
          return caches.delete(k);
        })
    );
    self.clients.claim();
    console.log('[SW] Activated and claimed clients');
  })());
});

// Fetch event - implement caching strategies
self.addEventListener('fetch', (event) => {
  const { request } = event;
  const url = new URL(request.url);

  // Skip caching for:
  // - Uploads
  // - HLS video segments
  // - API calls that should always be fresh
  // - POST/PUT/DELETE requests
  if (
    url.pathname.includes('/upload') ||
    url.pathname.includes('/uploader') ||
    url.pathname.includes('.m3u8') ||
    url.pathname.includes('.ts') ||
    url.pathname.includes('/api/') ||
    request.method !== 'GET'
  ) {
    return; // Network only
  }

  // NAVIGATION REQUESTS: Network-first with offline fallback
  if (request.mode === 'navigate') {
    event.respondWith(networkFirstStrategy(request, STATIC_CACHE));
    return;
  }

  // IMAGES: Cache-first with network fallback
  if (request.destination === 'image') {
    event.respondWith(cacheFirstStrategy(request, IMAGE_CACHE, CACHE_LIMITS.images));
    return;
  }

  // FONTS: Cache-first (fonts rarely change)
  if (request.destination === 'font' || url.pathname.match(/\.(woff2?|ttf|eot)$/)) {
    event.respondWith(cacheFirstStrategy(request, FONT_CACHE, CACHE_LIMITS.fonts));
    return;
  }

  // CSS/JS: Stale-while-revalidate
  if (request.destination === 'style' || request.destination === 'script') {
    event.respondWith(staleWhileRevalidate(request, STATIC_CACHE));
    return;
  }

  // VIDEO THUMBNAILS: Cache-first
  if (url.pathname.match(/thumb|thumbnail|preview/i) && url.pathname.match(/\.(jpg|jpeg|png|webp)$/)) {
    event.respondWith(cacheFirstStrategy(request, IMAGE_CACHE, CACHE_LIMITS.images));
    return;
  }

  // DEFAULT: Network-first
  event.respondWith(networkFirstStrategy(request, STATIC_CACHE));
});

// STRATEGY: Network-first with cache fallback
async function networkFirstStrategy(request, cacheName) {
  try {
    const networkResponse = await fetch(request);
    if (networkResponse && networkResponse.ok) {
      const cache = await caches.open(cacheName);
      cache.put(request, networkResponse.clone());
    }
    return networkResponse;
  } catch (error) {
    const cachedResponse = await caches.match(request);
    if (cachedResponse) {
      return cachedResponse;
    }
    // Return offline page for navigation requests
    if (request.mode === 'navigate') {
      return new Response(getOfflineHTML(), {
        headers: { 'Content-Type': 'text/html' }
      });
    }
    return Response.error();
  }
}

// STRATEGY: Cache-first with network fallback
async function cacheFirstStrategy(request, cacheName, limit) {
  const cachedResponse = await caches.match(request);
  if (cachedResponse) {
    return cachedResponse;
  }

  try {
    const networkResponse = await fetch(request);
    if (networkResponse && networkResponse.ok) {
      const cache = await caches.open(cacheName);
      cache.put(request, networkResponse.clone());
      // Limit cache size
      if (limit) {
        limitCacheSize(cacheName, limit);
      }
    }
    return networkResponse;
  } catch (error) {
    return Response.error();
  }
}

// STRATEGY: Stale-while-revalidate
async function staleWhileRevalidate(request, cacheName) {
  const cachedResponse = await caches.match(request);

  const fetchPromise = fetch(request).then((networkResponse) => {
    if (networkResponse && networkResponse.ok) {
      const cache = caches.open(cacheName);
      cache.then(c => c.put(request, networkResponse.clone()));
    }
    return networkResponse;
  }).catch(() => cachedResponse);

  return cachedResponse || fetchPromise;
}

// Limit cache size to prevent unlimited growth
async function limitCacheSize(cacheName, maxItems) {
  const cache = await caches.open(cacheName);
  const keys = await cache.keys();
  if (keys.length > maxItems) {
    // Delete oldest entries (FIFO)
    const deleteCount = keys.length - maxItems;
    for (let i = 0; i < deleteCount; i++) {
      await cache.delete(keys[i]);
    }
  }
}

// Offline page HTML
function getOfflineHTML() {
  return `
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Offline - EasyStream</title>
      <style>
        body {
          font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
          display: flex;
          align-items: center;
          justify-content: center;
          min-height: 100vh;
          margin: 0;
          background: #121212;
          color: #f0f0f0;
          text-align: center;
          padding: 20px;
        }
        .offline-container {
          max-width: 500px;
        }
        h1 {
          font-size: 2rem;
          margin-bottom: 1rem;
          color: #06a2cb;
        }
        p {
          font-size: 1.125rem;
          line-height: 1.6;
          margin-bottom: 2rem;
          color: #d0d0d0;
        }
        .retry-btn {
          display: inline-block;
          padding: 12px 24px;
          background: #06a2cb;
          color: white;
          text-decoration: none;
          border-radius: 8px;
          font-weight: 600;
          transition: background 200ms;
        }
        .retry-btn:hover {
          background: #92cefb;
        }
        .icon {
          font-size: 4rem;
          margin-bottom: 1rem;
        }
      </style>
    </head>
    <body>
      <div class="offline-container">
        <div class="icon">📡</div>
        <h1>You're Offline</h1>
        <p>It looks like you've lost your internet connection. Please check your network and try again.</p>
        <a href="javascript:location.reload()" class="retry-btn">Retry</a>
      </div>
    </body>
    </html>
  `;
}

// Handle messages from the main thread
self.addEventListener('message', (event) => {
  if (event.data && event.data.type === 'SKIP_WAITING') {
    self.skipWaiting();
  }
  if (event.data && event.data.type === 'CLEAR_CACHE') {
    event.waitUntil(
      caches.keys().then(keys => Promise.all(keys.map(key => caches.delete(key))))
    );
  }
});

// Background sync for offline actions (if supported)
if ('sync' in self.registration) {
  self.addEventListener('sync', (event) => {
    if (event.tag === 'sync-watch-history') {
      event.waitUntil(syncWatchHistory());
    }
  });
}

async function syncWatchHistory() {
  // Placeholder for syncing watch history when back online
  console.log('[SW] Syncing watch history...');
}

// Push notifications support
self.addEventListener('push', (event) => {
  const options = {
    body: event.data ? event.data.text() : 'New notification from EasyStream',
    icon: '/android-icon-192x192.svg',
    badge: '/android-icon-96x96.svg',
    vibrate: [200, 100, 200],
    data: {
      dateOfArrival: Date.now(),
      primaryKey: 1
    }
  };

  event.waitUntil(
    self.registration.showNotification('EasyStream', options)
  );
});

// Notification click handler
self.addEventListener('notificationclick', (event) => {
  event.notification.close();
  event.waitUntil(
    clients.openWindow('/')
  );
});

console.log('[SW] Service Worker v2.0 loaded');
