// ============================================================================
// service-worker.js - Enhanced PWA Service Worker with Push Notifications
// ============================================================================

const CACHE_VERSION = 'aims-v1.0.3';
const CACHE_NAME = `aims-cache-${CACHE_VERSION}`;

// Files to cache
const urlsToCache = [
  '/',
  '/dashboard/',
  '/marketplace/',
  '/prices/',
  '/chat/',
  '/offline.html',
  '/pwa/icons/icon-192x192.png',
  '/pwa/icons/icon-512x512.png',
  'https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css',
  'https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css',
  'https://code.jquery.com/jquery-3.7.1.min.js',
  'https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js'
];

// ============================================================================
// INSTALL - Cache assets
// ============================================================================
self.addEventListener('install', event => {
  console.log('[SW] Installing...');
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => {
        console.log('[SW] Caching app shell');
        return cache.addAll(urlsToCache);
      })
      .then(() => self.skipWaiting())
  );
});

// ============================================================================
// ACTIVATE - Clean old caches
// ============================================================================
self.addEventListener('activate', event => {
  console.log('[SW] Activating...');
  event.waitUntil(
    caches.keys().then(cacheNames => {
      return Promise.all(
        cacheNames.map(cacheName => {
          if (cacheName !== CACHE_NAME) {
            console.log('[SW] Deleting old cache:', cacheName);
            return caches.delete(cacheName);
          }
        })
      );
    }).then(() => self.clients.claim())
  );
});

// ============================================================================
// FETCH - Network first for API, Cache first for static
// ============================================================================
self.addEventListener('fetch', event => {
  const { request } = event;
  
  // Skip non-GET requests
  if (request.method !== 'GET') {
    return;
  }
  
  // Network first for API/AJAX calls
  if (request.url.includes('/api/') || request.url.includes('/ajax/')) {
    event.respondWith(
      fetch(request)
        .catch(() => {
          return new Response(
            JSON.stringify({ 
              success: false, 
              message: 'You are offline. Changes will sync when online.' 
            }),
            { headers: { 'Content-Type': 'application/json' } }
          );
        })
    );
    return;
  }
  
  // Cache first for static assets
  event.respondWith(
    caches.match(request)
      .then(response => {
        if (response) {
          return response;
        }
        
        return fetch(request).then(response => {
          // Don't cache non-successful responses
          if (!response || response.status !== 200 || response.type === 'error') {
            return response;
          }
          
          // Clone the response
          const responseToCache = response.clone();
          
          caches.open(CACHE_NAME)
            .then(cache => {
              cache.put(request, responseToCache);
            });
          
          return response;
        });
      })
      .catch(() => {
        // Return offline page for navigation requests
        if (request.mode === 'navigate') {
          return caches.match('/offline.html');
        }
      })
  );
});

// ============================================================================
// PUSH NOTIFICATION - Handle incoming push messages
// ============================================================================
self.addEventListener('push', event => {
  console.log('[SW] Push received:', event);
  
  let notificationData = {
    title: 'AIMS',
    body: 'You have a new notification',
    icon: '/pwa/icons/icon-192x192.png',
    badge: '/pwa/icons/badge-96x96.png',
    tag: 'aims-notification',
    data: {
      url: '/'
    }
  };

  // Parse push data if available
  if (event.data) {
    try {
      const data = event.data.json();
      notificationData = {
        title: data.title || 'AIMS',
        body: data.body || data.message || 'New notification',
        icon: data.icon || '/pwa/icons/icon-192x192.png',
        badge: '/pwa/icons/badge-96x96.png',
        image: data.image || null,
        tag: data.tag || 'aims-notification',
        data: {
          url: data.url || data.link || '/',
          notificationId: data.id || null,
          type: data.type || 'info'
        },
        vibrate: data.vibrate || [200, 100, 200],
        requireInteraction: data.requireInteraction || false,
        actions: data.actions || [
          { action: 'open', title: 'Open', icon: '/pwa/icons/icon-96x96.png' },
          { action: 'close', title: 'Dismiss' }
        ]
      };
    } catch (e) {
      console.error('[SW] Error parsing push data:', e);
    }
  }

  event.waitUntil(
    Promise.all([
      // Show notification
      self.registration.showNotification(notificationData.title, notificationData),
      
      // Update app badge
      updateAppBadge()
    ])
  );
});

// ============================================================================
// NOTIFICATION CLICK - Handle user clicking notification
// ============================================================================
self.addEventListener('notificationclick', event => {
  console.log('[SW] Notification clicked:', event);
  
  event.notification.close();

  const urlToOpen = event.notification.data?.url || '/';
  const notificationId = event.notification.data?.notificationId;

  event.waitUntil(
    clients.matchAll({ type: 'window', includeUncontrolled: true })
      .then(clientList => {
        // Check if there's already a window open
        for (let client of clientList) {
          if (client.url === urlToOpen && 'focus' in client) {
            return client.focus();
          }
        }
        
        // Open new window if none exists
        if (clients.openWindow) {
          return clients.openWindow(urlToOpen);
        }
      })
      .then(() => {
        // Mark notification as read via API
        if (notificationId && event.action === 'open') {
          return fetch('/ajax/mark-notification-read.php', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: `notification_id=${notificationId}`
          });
        }
      })
      .then(() => updateAppBadge())
  );
});

// ============================================================================
// NOTIFICATION CLOSE - Handle notification being dismissed
// ============================================================================
self.addEventListener('notificationclose', event => {
  console.log('[SW] Notification closed:', event);
  
  // Update badge when notification is dismissed
  event.waitUntil(updateAppBadge());
});

// ============================================================================
// BACKGROUND SYNC - Sync messages when back online
// ============================================================================
self.addEventListener('sync', event => {
  console.log('[SW] Background sync:', event.tag);
  
  if (event.tag === 'sync-messages') {
    event.waitUntil(syncMessages());
  } else if (event.tag === 'sync-notifications') {
    event.waitUntil(syncNotifications());
  }
});

// ============================================================================
// PERIODIC BACKGROUND SYNC - Check for updates periodically (Chrome/Edge)
// ============================================================================
self.addEventListener('periodicsync', event => {
  console.log('[SW] Periodic sync:', event.tag);
  
  if (event.tag === 'check-updates') {
    event.waitUntil(
      checkForUpdates().then(() => updateAppBadge())
    );
  }
});

// ============================================================================
// MESSAGE - Handle messages from client
// ============================================================================
self.addEventListener('message', event => {
  console.log('[SW] Message received:', event.data);
  
  if (event.data.type === 'SKIP_WAITING') {
    self.skipWaiting();
  } else if (event.data.type === 'UPDATE_BADGE') {
    updateAppBadge();
  } else if (event.data.type === 'CLEAR_BADGE') {
    clearAppBadge();
  }
});

// ============================================================================
// HELPER FUNCTIONS
// ============================================================================

/**
 * Update app badge with current unread count
 */
async function updateAppBadge() {
  try {
    // Fetch unread counts from server
    const [notifRes, msgRes] = await Promise.all([
      fetch('/ajax/notifications.php').then(r => r.json()).catch(() => ({ unread_count: 0 })),
      fetch('/ajax/unread-messages.php').then(r => r.json()).catch(() => ({ unread_count: 0 }))
    ]);

    const totalUnread = (notifRes.unread_count || 0) + (msgRes.unread_count || 0);

    // Update badge on app icon
    if (totalUnread > 0) {
      if (self.registration.setAppBadge) {
        await self.registration.setAppBadge(totalUnread);
      }
    } else {
      if (self.registration.clearAppBadge) {
        await self.registration.clearAppBadge();
      }
    }

    console.log('[SW] Badge updated:', totalUnread);
    return totalUnread;
    
  } catch (error) {
    console.error('[SW] Failed to update badge:', error);
    return 0;
  }
}

/**
 * Clear app badge
 */
async function clearAppBadge() {
  try {
    if (self.registration.clearAppBadge) {
      await self.registration.clearAppBadge();
      console.log('[SW] Badge cleared');
    }
  } catch (error) {
    console.error('[SW] Failed to clear badge:', error);
  }
}

/**
 * Sync pending messages
 */
async function syncMessages() {
  try {
    const cache = await caches.open('pending-messages');
    const requests = await cache.keys();
    
    const results = await Promise.all(
      requests.map(async request => {
        try {
          const response = await fetch(request.clone());
          if (response.ok) {
            await cache.delete(request);
            return { success: true };
          }
          return { success: false };
        } catch (error) {
          return { success: false, error };
        }
      })
    );
    
    console.log('[SW] Messages synced:', results);
    await updateAppBadge();
    
  } catch (error) {
    console.error('[SW] Sync failed:', error);
  }
}

/**
 * Sync notifications
 */
async function syncNotifications() {
  try {
    await updateAppBadge();
    console.log('[SW] Notifications synced');
  } catch (error) {
    console.error('[SW] Notification sync failed:', error);
  }
}

/**
 * Check for updates from server
 */
async function checkForUpdates() {
  try {
    // This could check for new notifications/messages
    // and show a notification if there are updates
    const totalUnread = await updateAppBadge();
    
    if (totalUnread > 0) {
      // Optionally show a silent notification
      // Only if explicitly requested by server
    }
    
    return totalUnread;
    
  } catch (error) {
    console.error('[SW] Failed to check updates:', error);
    return 0;
  }
}