const CACHE_VERSION = "v2"
const CACHE_NAME = `musique-${CACHE_VERSION}`
const RUNTIME_CACHE = `musique-runtime-${CACHE_VERSION}`
const IMAGE_CACHE = `musique-images-${CACHE_VERSION}`
const AUDIO_CACHE = `musique-audio-${CACHE_VERSION}`
const API_CACHE = `musique-api-${CACHE_VERSION}`

// Pages to cache for offline access
const STATIC_ASSETS = [
  "/",
  "/home",
  "/search",
  "/library",
  "/downloads",
  "/offline",
  "/login",
  "/liked",
  "/profile",
  "/settings",
  "/manifest.json",
  "/icons/icon-192x192.jpg",
  "/icons/icon-512x512.jpg",
  "/abstract-music-album.png",
]

// API endpoints to cache for offline
const CACHEABLE_API_ROUTES = [
  "/api/genres",
  "/api/categories",
  "/api/playlists",
  "/api/tracks/featured",
  "/api/tracks/trending",
]

// Install event - cache static assets
self.addEventListener("install", (event) => {
  console.log("[SW] Installing service worker...")
  event.waitUntil(
    caches.open(CACHE_NAME).then((cache) => {
      console.log("[SW] Caching static assets")
      return cache.addAll(STATIC_ASSETS).catch((err) => {
        console.error("[SW] Failed to cache some assets:", err)
      })
    }),
  )
  self.skipWaiting()
})

// Activate event - clean up old caches
self.addEventListener("activate", (event) => {
  console.log("[SW] Activating service worker...")
  const currentCaches = [CACHE_NAME, RUNTIME_CACHE, IMAGE_CACHE, AUDIO_CACHE, API_CACHE]
  
  event.waitUntil(
    caches.keys().then((cacheNames) => {
      return Promise.all(
        cacheNames
          .filter((name) => name.startsWith("musique-") && !currentCaches.includes(name))
          .map((name) => {
            console.log("[SW] Deleting old cache:", name)
            return caches.delete(name)
          }),
      )
    }),
  )
  self.clients.claim()
})

self.addEventListener("fetch", (event) => {
  const { request } = event
  const url = new URL(request.url)

  // Skip non-GET requests
  if (request.method !== "GET") return

  // Handle API requests
  if (url.pathname.startsWith("/api/")) {
    // Check if this is a cacheable API route
    const isCacheable = CACHEABLE_API_ROUTES.some(route => 
      url.pathname === route || url.pathname.startsWith(route + "/")
    )

    if (isCacheable) {
      // Network-first with cache fallback for important API data
      event.respondWith(
        fetch(request)
          .then((response) => {
            if (response.ok) {
              const responseClone = response.clone()
              caches.open(API_CACHE).then((cache) => {
                cache.put(request, responseClone)
              })
            }
            return response
          })
          .catch(async () => {
            const cached = await caches.match(request)
            if (cached) {
              console.log("[SW] Serving cached API:", url.pathname)
              return cached
            }
            // Return empty data structure for offline
            return new Response(JSON.stringify({ 
              error: "Offline", 
              offline: true,
              data: [],
              tracks: [],
              genres: [],
              playlists: []
            }), {
              status: 200, // Return 200 so app can handle gracefully
              headers: { "Content-Type": "application/json" },
            })
          }),
      )
      return
    }

    // For user-specific API routes, try network then fail gracefully
    if (url.pathname.includes("/users/") || url.pathname.includes("/auth/")) {
      event.respondWith(
        fetch(request).catch(() => {
          return new Response(JSON.stringify({ 
            error: "Offline", 
            offline: true 
          }), {
            status: 200,
            headers: { "Content-Type": "application/json" },
          })
        })
      )
      return
    }

    // For streaming/audio APIs, let them fail naturally if offline
    if (url.pathname.startsWith("/api/stream/")) {
      return // Don't intercept, let IndexedDB handle offline audio
    }

    return
  }

  if (request.mode === "navigate") {
    event.respondWith(
      fetch(request)
        .then((response) => {
          // Cache successful navigations
          if (response.ok) {
            const responseClone = response.clone()
            caches.open(RUNTIME_CACHE).then((cache) => {
              cache.put(request, responseClone)
            })
          }
          return response
        })
        .catch(() => {
          return caches.match(request).then((cached) => {
            if (cached) {
              console.log("[SW] Serving cached page:", url.pathname)
              return cached
            }
            // If offline and no cache, show offline page
            return caches.match("/offline").then((offlinePage) => {
              if (offlinePage) {
                console.log("[SW] Serving offline page")
                return offlinePage
              }
              // Fallback HTML for offline
              return new Response(
                `<!DOCTYPE html>
                <html>
                <head>
                  <meta charset="utf-8">
                  <meta name="viewport" content="width=device-width, initial-scale=1">
                  <title>Hors ligne - Musique</title>
                  <style>
                    body { font-family: system-ui, sans-serif; display: flex; align-items: center; justify-content: center; min-height: 100vh; margin: 0; background: #0a0a0a; color: #fff; text-align: center; padding: 20px; }
                    .container { max-width: 400px; }
                    h1 { font-size: 24px; margin-bottom: 16px; }
                    p { color: #888; margin-bottom: 24px; }
                    button { background: #a855f7; color: white; border: none; padding: 12px 24px; border-radius: 8px; font-size: 16px; cursor: pointer; }
                    button:hover { background: #9333ea; }
                  </style>
                </head>
                <body>
                  <div class="container">
                    <h1>Vous êtes hors ligne</h1>
                    <p>Pas de connexion internet. Vous pouvez toujours écouter vos titres téléchargés.</p>
                    <button onclick="window.location.href='/downloads'">Mes téléchargements</button>
                  </div>
                </body>
                </html>`,
                {
                  status: 503,
                  statusText: "Service Unavailable",
                  headers: { "Content-Type": "text/html; charset=utf-8" },
                },
              )
            })
          })
        }),
    )
    return
  }

  if (url.pathname.match(/\.(png|jpg|jpeg|svg|webp|gif|ico)$/)) {
    event.respondWith(
      caches.open(IMAGE_CACHE).then((cache) => {
        return cache.match(request).then((cached) => {
          const fetchPromise = fetch(request)
            .then((response) => {
              if (response.ok) {
                cache.put(request, response.clone())
              }
              return response
            })
            .catch(() => cached) // Return cached on fetch error

          // Return cached immediately, update in background
          return cached || fetchPromise
        })
      }),
    )
    return
  }

  if (url.pathname.match(/\.(js|css|woff2?)$/) || url.pathname.startsWith("/_next/static/")) {
    event.respondWith(
      caches.match(request).then((cached) => {
        if (cached) return cached
        return fetch(request)
          .then((response) => {
            if (response.ok) {
              const responseClone = response.clone()
              caches.open(CACHE_NAME).then((cache) => {
                cache.put(request, responseClone)
              })
            }
            return response
          })
          .catch(() => {
            console.error("[SW] Failed to fetch static asset:", url.pathname)
            return new Response("Asset unavailable offline", { status: 503 })
          })
      }),
    )
    return
  }

  // Default: try network first, fallback to cache
  event.respondWith(
    fetch(request)
      .then((response) => {
        if (response.ok && !url.pathname.startsWith("/api/")) {
          const responseClone = response.clone()
          caches.open(RUNTIME_CACHE).then((cache) => {
            cache.put(request, responseClone)
          })
        }
        return response
      })
      .catch(() => caches.match(request)),
  )
})

// Handle background sync for offline actions
self.addEventListener("sync", (event) => {
  console.log("[SW] Background sync:", event.tag)
  if (event.tag === "sync-play-history") {
    event.waitUntil(syncPlayHistory())
  }
})

async function syncPlayHistory() {
  // Sync any pending play history when back online
  console.log("[SW] Syncing play history...")
}

// Handle push notifications (optional)
self.addEventListener("push", (event) => {
  if (!event.data) return

  const data = event.data.json()

  event.waitUntil(
    self.registration.showNotification(data.title, {
      body: data.body,
      icon: "/icons/icon-192x192.jpg",
      badge: "/icons/badge-72x72.png",
      data: data.url,
    }),
  )
})

self.addEventListener("notificationclick", (event) => {
  event.notification.close()

  if (event.notification.data) {
    event.waitUntil(clients.openWindow(event.notification.data))
  }
})

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((cacheNames) => {
        return Promise.all(cacheNames.map((name) => caches.delete(name)))
      }),
    )
  }
})
