// Generated Service Worker - Version v0.0.0
// Generated on: 2025-09-16T16:49:12.433Z

const CACHE_NAME = 'cpw-spoof-v0.0.0';
const STATIC_CACHE_NAME = 'cpw-spoof-static-v0.0.0';
const DYNAMIC_CACHE_NAME = 'cpw-spoof-dynamic-v0.0.0';
const MAX_CACHE_AGE = 604800000;
const MAX_CACHE_SIZE = 100;

// Assets to cache immediately on install
const STATIC_ASSETS = [
  "/",
  "/index.html",
  "/manifest.json",
  "/poppulo-logo.svg",
  "/assets/main-BHio2sGw.css",
  "/assets/main-DIRj75x1.js"
];

// API endpoints configuration
const API_ENDPOINTS = [
  "/api/",
  "/graphql"
];

// Custom strategies configuration
const CUSTOM_STRATEGIES = {
  "/assets/": "cacheFirst",
  "/images/": "cacheFirst",
  "/fonts/": "cacheFirst"
};

// Install event - cache static assets
self.addEventListener('install', (event) => {
  console.log('[SW] Installing service worker...');
  
  event.waitUntil(
    Promise.all([
      caches.open(STATIC_CACHE_NAME).then((cache) => {
        console.log('[SW] Caching static assets');
        return cache.addAll(STATIC_ASSETS);
      }),
      self.skipWaiting()
    ])
  );
});

// Activate event - clean up old caches
self.addEventListener('activate', (event) => {
  console.log('[SW] Activating service worker...');
  
  event.waitUntil(
    Promise.all([
      caches.keys().then((cacheNames) => {
        return Promise.all(
          cacheNames.map((cacheName) => {
            if (!cacheName.includes('cpw-spoof-v0.0.0')) {
              console.log('[SW] Deleting old cache:', cacheName);
              return caches.delete(cacheName);
            }
          })
        );
      }),
      self.clients.claim()
    ])
  );
});

// Fetch event - serve from cache with configured strategy
self.addEventListener('fetch', (event) => {
  const request = event.request;
  const url = new URL(request.url);
  
  if (request.method !== 'GET') return;
  if (!url.protocol.startsWith('http')) return;
  
  // Check for custom strategies first
  for (const [pattern, strategy] of Object.entries(CUSTOM_STRATEGIES)) {
    if (url.pathname.includes(pattern)) {
      event.respondWith(executeStrategy(request, strategy));
      return;
    }
  }
  
  // Default strategies
  if (isStaticAsset(url)) {
    event.respondWith(executeStrategy(request, 'cacheFirst'));
  } else if (isAPIRequest(url)) {
    event.respondWith(executeStrategy(request, 'networkFirst'));
  } else {
    event.respondWith(executeStrategy(request, 'staleWhileRevalidate'));
  }
});

// Cache strategies
async function executeStrategy(request, strategy) {
  switch (strategy) {
    case 'cacheFirst':
      return cacheFirst(request);
    case 'networkFirst':
      return networkFirst(request);
    case 'staleWhileRevalidate':
      return staleWhileRevalidate(request);
    default:
      return fetch(request);
  }
}

async function cacheFirst(request) {
  try {
    const cache = await caches.open(STATIC_CACHE_NAME);
    const cachedResponse = await cache.match(request);
    
    if (cachedResponse && !isExpired(cachedResponse)) {
      return cachedResponse;
    }
    
    const networkResponse = await fetch(request);
    if (networkResponse.ok) {
      await cache.put(request, networkResponse.clone());
      await limitCacheSize(cache);
    }
    return networkResponse;
  } catch (error) {
    const cache = await caches.open(STATIC_CACHE_NAME);
    const fallback = await cache.match(request);
    if (fallback) return fallback;
    
    if (request.destination === 'document') {
      return cache.match('/index.html') || new Response('Offline', { status: 503 });
    }
    throw error;
  }
}

async function networkFirst(request) {
  try {
    const networkResponse = await fetch(request);
    if (networkResponse.ok) {
      const cache = await caches.open(DYNAMIC_CACHE_NAME);
      await cache.put(request, networkResponse.clone());
      await limitCacheSize(cache);
    }
    return networkResponse;
  } catch (error) {
    const cache = await caches.open(DYNAMIC_CACHE_NAME);
    const cachedResponse = await cache.match(request);
    if (cachedResponse && !isExpired(cachedResponse)) {
      return cachedResponse;
    }
    throw error;
  }
}

async function staleWhileRevalidate(request) {
  const cache = await caches.open(DYNAMIC_CACHE_NAME);
  const cachedResponse = await cache.match(request);
  
  const fetchPromise = fetch(request).then(async (networkResponse) => {
    if (networkResponse.ok) {
      await cache.put(request, networkResponse.clone());
      await limitCacheSize(cache);
    }
    return networkResponse;
  }).catch(() => null);
  
  if (cachedResponse && !isExpired(cachedResponse)) {
    return cachedResponse;
  }
  
  return fetchPromise || cachedResponse || new Response('Offline', { status: 503 });
}

// Helper functions
function isStaticAsset(url) {
  const staticExtensions = ['.js', '.css', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico', '.woff', '.woff2', '.ttf'];
  const pathname = url.pathname.toLowerCase();
  
  return staticExtensions.some(ext => pathname.endsWith(ext)) ||
         pathname.includes('/assets/') ||
         pathname.includes('/static/') ||
         STATIC_ASSETS.includes(pathname);
}

function isAPIRequest(url) {
  return API_ENDPOINTS.some(endpoint => url.pathname.startsWith(endpoint)) ||
         url.hostname !== location.hostname;
}

function isExpired(response) {
  const dateHeader = response.headers.get('date');
  if (!dateHeader) return false;
  
  const responseDate = new Date(dateHeader);
  const now = new Date();
  return (now.getTime() - responseDate.getTime()) > MAX_CACHE_AGE;
}

async function limitCacheSize(cache) {
  const requests = await cache.keys();
  if (requests.length > MAX_CACHE_SIZE) {
    // Remove oldest entries
    const sortedRequests = requests.sort((a, b) => {
      const aDate = new Date(a.headers.get('date') || 0);
      const bDate = new Date(b.headers.get('date') || 0);
      return aDate - bDate;
    });
    
    const toDelete = sortedRequests.slice(0, requests.length - MAX_CACHE_SIZE);
    await Promise.all(toDelete.map(request => cache.delete(request)));
  }
}

async function getCacheSize() {
  const cacheNames = await caches.keys();
  let totalSize = 0;
  
  for (const cacheName of cacheNames) {
    const cache = await caches.open(cacheName);
    const requests = await cache.keys();
    totalSize += requests.length;
  }
  
  return totalSize;
}

async function clearAllCaches() {
  const cacheNames = await caches.keys();
  await Promise.all(cacheNames.map(name => caches.delete(name)));
}

// Message handling
self.addEventListener('message', (event) => {
  const { type, data } = event.data;
  
  switch (type) {
    case 'SKIP_WAITING':
      self.skipWaiting();
      break;
      
    case 'GET_CACHE_SIZE':
      getCacheSize().then(size => {
        event.ports[0].postMessage({ type: 'CACHE_SIZE', size });
      });
      break;
      
    case 'CLEAR_CACHE':
      clearAllCaches().then(() => {
        event.ports[0].postMessage({ type: 'CACHE_CLEARED' });
      });
      break;
      
    case 'CACHE_URLS':
      if (data && data.urls) {
        cacheUrls(data.urls).then(() => {
          event.ports[0].postMessage({ type: 'URLS_CACHED' });
        });
      }
      break;
  }
});

async function cacheUrls(urls) {
  const cache = await caches.open(DYNAMIC_CACHE_NAME);
  
  for (const url of urls) {
    try {
      const response = await fetch(url);
      if (response.ok) {
        await cache.put(url, response);
      }
    } catch (error) {
      console.error('[SW] Failed to cache:', url, error);
    }
  }
}

// Handle iframe-specific concerns
self.addEventListener('fetch', (event) => {
  const request = event.request;
  const url = new URL(request.url);
  
  // Add headers to support iframe usage
  if (request.destination === 'document' || request.destination === 'iframe') {
    event.respondWith(
      fetch(request).then(response => {
        if (response.ok && response.headers.get('content-type')?.includes('text/html')) {
          const headers = new Headers(response.headers);
          headers.set('X-Frame-Options', 'ALLOWALL');
          headers.delete('X-Frame-Options'); // Remove restrictive frame options
          
          return new Response(response.body, {
            status: response.status,
            statusText: response.statusText,
            headers: headers
          });
        }
        return response;
      }).catch(() => {
        // Fallback to cached version for iframe
        return caches.match(request) || 
               caches.match('/index.html') ||
               new Response('Offline', { status: 503 });
      })
    );
  }
});

console.log('[SW] Service worker loaded and ready for iframe usage');