/**
 * OTIS Service Worker — Full Offline Engine
 * Version: 2.0.0
 * Strategy: Cache-First for static, Network-First for API/dynamic
 */

const CACHE_NAME = 'otis-v2';
const OFFLINE_URL = '/OTIS/public/offline.html';

// Static assets cached on install
const STATIC_ASSETS = [
    '/OTIS/',
    '/OTIS/public/offline.html',
    '/OTIS/public/manifest.json',
    // Bootstrap RTL
    'https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.rtl.min.css',
    'https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js',
    // FontAwesome
    'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css',
    // Google Fonts
    'https://fonts.googleapis.com/css2?family=Cairo:wght@400;500;600;700;800&family=Tajawal:wght@400;500;700;800&display=swap',
    // ChartJS
    'https://cdn.jsdelivr.net/npm/chart.js@4.4.2/dist/chart.umd.min.js',
    // OTIS Assets
    '/OTIS/assets/css/style-rtl.css',
    '/OTIS/assets/css/mobile.css',
    '/OTIS/assets/js/main.js',
    '/OTIS/assets/js/offline-sync.js',
    '/OTIS/assets/js/push-notifications.js',
];

// Pages to cache for offline access
const PAGE_CACHE_NAME = 'otis-pages-v2';
const CACHED_PAGES = [
    '/OTIS/',
    '/OTIS/todo',
    '/OTIS/health',
    '/OTIS/finance',
    '/OTIS/habits',
    '/OTIS/journal',
    '/OTIS/calendar',
];

// API routes — network-first, sync queue if offline
const API_PATTERNS = [
    '/OTIS/todo/',
    '/OTIS/health/',
    '/OTIS/finance/',
    '/OTIS/habits/',
    '/OTIS/journal/',
    '/OTIS/calendar/',
];

// ===== INSTALL =====
self.addEventListener('install', (event) => {
    console.log('[OTIS SW] Installing v2...');
    event.waitUntil(
        Promise.all([
            caches.open(CACHE_NAME).then(cache => {
                // Cache static assets, ignore failures for external resources
                return Promise.allSettled(
                    STATIC_ASSETS.map(url =>
                        cache.add(url).catch(err => console.warn('[OTIS SW] Failed to cache:', url, err))
                    )
                );
            }),
            caches.open(PAGE_CACHE_NAME).then(cache => {
                return Promise.allSettled(
                    CACHED_PAGES.map(url =>
                        cache.add(url).catch(err => console.warn('[OTIS SW] Failed to cache page:', url, err))
                    )
                );
            })
        ]).then(() => self.skipWaiting())
    );
});

// ===== ACTIVATE =====
self.addEventListener('activate', (event) => {
    console.log('[OTIS SW] Activated v2');
    event.waitUntil(
        caches.keys().then(keys => {
            return Promise.all(
                keys
                    .filter(k => k !== CACHE_NAME && k !== PAGE_CACHE_NAME)
                    .map(k => {
                        console.log('[OTIS SW] Deleting old cache:', k);
                        return caches.delete(k);
                    })
            );
        }).then(() => self.clients.claim())
    );
});

// ===== FETCH INTERCEPTOR =====
self.addEventListener('fetch', (event) => {
    const { request } = event;
    const url = new URL(request.url);

    // Skip non-GET offline sync (POST handled by client)
    if (request.method !== 'GET') return;

    // Skip browser-extension requests
    if (!url.protocol.startsWith('http')) return;

    // Strategy: Cache-first for static assets
    if (isStaticAsset(url)) {
        event.respondWith(cacheFirst(request));
        return;
    }

    // Strategy: Network-first for OTIS pages, fallback to cache
    if (isOtisPage(url)) {
        event.respondWith(networkFirstWithPageFallback(request));
        return;
    }

    // Default: network-first
    event.respondWith(networkFirst(request));
});

// ===== STRATEGIES =====

async function cacheFirst(request) {
    const cached = await caches.match(request);
    if (cached) return cached;

    try {
        const response = await fetch(request);
        if (response.ok) {
            const cache = await caches.open(CACHE_NAME);
            cache.put(request, response.clone());
        }
        return response;
    } catch (e) {
        return new Response('Offline — resource not cached', { status: 503 });
    }
}

async function networkFirst(request) {
    try {
        const response = await fetch(request);
        if (response.ok) {
            const cache = await caches.open(CACHE_NAME);
            cache.put(request, response.clone());
        }
        return response;
    } catch (e) {
        const cached = await caches.match(request);
        if (cached) return cached;
        return new Response('Offline', { status: 503 });
    }
}

async function networkFirstWithPageFallback(request) {
    try {
        const response = await fetch(request);
        if (response.ok) {
            const cache = await caches.open(PAGE_CACHE_NAME);
            cache.put(request, response.clone());
        }
        return response;
    } catch (e) {
        // 1. Try exact cached page
        const cached = await caches.match(request);
        if (cached) return cached;

        // 2. Try cached root
        const rootCached = await caches.match('/OTIS/');
        if (rootCached) return rootCached;

        // 3. Fallback to offline page
        const offlinePage = await caches.match(OFFLINE_URL);
        if (offlinePage) return offlinePage;

        return new Response('<h1>أنت غير متصل</h1>', {
            status: 503,
            headers: { 'Content-Type': 'text/html; charset=utf-8' }
        });
    }
}

// ===== HELPERS =====

function isStaticAsset(url) {
    return (
        url.pathname.includes('/assets/') ||
        url.hostname.includes('cdn.jsdelivr.net') ||
        url.hostname.includes('cdnjs.cloudflare.com') ||
        url.hostname.includes('fonts.googleapis.com') ||
        url.hostname.includes('fonts.gstatic.com') ||
        url.pathname.endsWith('.css') ||
        url.pathname.endsWith('.js') ||
        url.pathname.endsWith('.woff2') ||
        url.pathname.endsWith('.woff') ||
        url.pathname.endsWith('.ttf') ||
        url.pathname.endsWith('.png') ||
        url.pathname.endsWith('.svg') ||
        url.pathname.endsWith('.ico')
    );
}

function isOtisPage(url) {
    return (
        url.hostname === location.hostname &&
        url.pathname.startsWith('/OTIS') &&
        !url.pathname.includes('/api/') &&
        !url.pathname.includes('?') &&
        !url.searchParams.has('json')
    );
}

// ===== BACKGROUND SYNC =====
self.addEventListener('sync', (event) => {
    if (event.tag === 'otis-offline-sync') {
        console.log('[OTIS SW] Background Sync triggered');
        event.waitUntil(processOfflineQueue());
    }
});

async function processOfflineQueue() {
    // Notify all open clients to trigger sync
    const clients = await self.clients.matchAll({ type: 'window' });
    clients.forEach(client => {
        client.postMessage({ type: 'OTIS_SYNC_NOW' });
    });
}

// ===== PUSH MESSAGES FROM MAIN THREAD =====
self.addEventListener('message', (event) => {
    if (event.data && event.data.type === 'SKIP_WAITING') {
        self.skipWaiting();
    }
    if (event.data && event.data.type === 'CACHE_PAGE') {
        const url = event.data.url;
        caches.open(PAGE_CACHE_NAME).then(cache => cache.add(url)).catch(() => {});
    }
});
