/* firebase-messaging-sw.js */

importScripts('https://www.gstatic.com/firebasejs/10.8.1/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/10.8.1/firebase-messaging-compat.js');

/* ------------------------------
 * 🧩 生命周期：install / activate
 * ------------------------------ */
self.addEventListener('install', (event) => {
  // 立即进入 waiting -> activate
  self.skipWaiting();
});

self.addEventListener('activate', (event) => {
  event.waitUntil((async () => {
    // 让新 SW 立即接管页面
    await self.clients.claim();

    // 🔥 关键：activate 预热（强制读取 IDB + 初始化 Firebase）
    try {
      console.log('[SW] activate → preload firebase');
      await ensureFirebaseReady();
      console.log('[SW] firebase preloaded');
    } catch (e) {
      console.error('[SW] preload firebase failed:', e);
      // 不要 throw，activate 仍然要完成；后续 push 还能重试
    }
  })());
});

/* ------------------------------
 * 🧭 事件映射表
 * ------------------------------ */
const eventNameMap = {
  notification_receive: 'NOTIFICATION_RECEIVE',
  notification_display: 'NOTIFICATION_DISPLAY',
  notification_click: 'NOTIFICATION_CLICK',
  notification_dismiss: 'NOTIFICATION_DISMISS',
  notification_open: 'NOTIFICATION_OPEN',
  notification_engagement: 'NOTIFICATION_ENGAGEMENT',
};

/* ------------------------------
 * 🔌 Firebase 初始化单例
 * ------------------------------ */
let messaging = null;
let isFirebaseInitialized = false;
let firebaseConfigCache = null;
let firebaseInitPromise = null;

// 去重缓存：避免 push 兜底 + firebase onBackgroundMessage 双弹
const seen = new Map(); // id -> timestamp
function isDuplicate(id, ttlMs = 60_000) {
  if (!id) return false;
  const now = Date.now();
  for (const [k, t] of seen) {
    if (now - t > ttlMs) seen.delete(k);
  }
  if (seen.has(id)) return true;
  seen.set(id, now);
  return false;
}

async function ensureFirebaseReady() {
  if (isFirebaseInitialized) return true;

  if (!firebaseInitPromise) {
    firebaseInitPromise = (async () => {
      await initFirebase(); // 失败必须 throw
      return true;
    })().catch((e) => {
      // 失败允许重试
      firebaseInitPromise = null;
      throw e;
    });
  }
  return firebaseInitPromise;
}

/* ------------------------------
 * 🗄️ IndexedDB 读取 Firebase Config
 * ------------------------------ */
async function getFBFromIndexedDB() {
  // 你当前的配置
  const DB_NAME = '_astorage';
  const DB_VERSION = 2;
  const STORE_NAME = 'renkv';
  const KEY = 'firebaseConfig';

  return new Promise((resolve, reject) => {
    const request = indexedDB.open(DB_NAME, DB_VERSION);

    request.onupgradeneeded = (event) => {
      const db = event.target.result;
      if (!db.objectStoreNames.contains(STORE_NAME)) {
        db.createObjectStore(STORE_NAME, { keyPath: 'id' });
      }
    };

    request.onsuccess = (event) => {
      const db = event.target.result;

      db.onversionchange = () => {
        console.warn('[IndexedDB] version change → closing db');
        db.close();
      };

      if (!db.objectStoreNames.contains(STORE_NAME)) {
        db.close();
        return reject(new Error(`[IndexedDB] object store "${STORE_NAME}" not found`));
      }

      // ✅ 只读事务
      const tx = db.transaction([STORE_NAME], 'readonly');
      const store = tx.objectStore(STORE_NAME);
      const getReq = store.get(KEY);

      getReq.onsuccess = () => {
        try {
          const raw = getReq.result;
          // 兼容两种常见存法：
          // 1) 直接存 config 对象/字符串
          // 2) 存 { id: 'firebaseConfig', value: '...' / {...} }
          const val = raw?.value ?? raw;
          const cfg = val
            ? (typeof val === 'string' ? JSON.parse(val) : val)
            : null;

          resolve(cfg);
        } catch (e) {
          reject(e);
        } finally {
          db.close();
        }
      };

      getReq.onerror = () => {
        const err = getReq.error || new Error('[IndexedDB] get failed');
        db.close();
        reject(err);
      };

      tx.onerror = (e) => {
        db.close();
        reject(e?.target?.error || e);
      };
    };

    request.onerror = (event) => {
      reject(event?.target?.error || new Error('[IndexedDB] open failed'));
    };
  });
}

/* ------------------------------
 * 🚀 Firebase 初始化
 * ------------------------------ */
async function initFirebase() {
  if (isFirebaseInitialized) return;

  let config = firebaseConfigCache;
  if (!config) {
    // 1) 优先全局注入（如构建时替换）
    if (typeof _FIREBASE_CONFIG_ !== 'undefined' && _FIREBASE_CONFIG_) {
      config = _FIREBASE_CONFIG_;
    } else {
      // 2) 再从 IndexedDB 读
      config = await getFBFromIndexedDB();
    }
  }

  if (!config || !config.messagingSenderId) {
    throw new Error('[SW] Firebase config missing or invalid');
  }

  // ✅ 避免重复 initializeApp
  if (!firebase.apps || !firebase.apps.length) {
    firebase.initializeApp(config);
  }

  firebaseConfigCache = config;

  messaging = firebase.messaging();
  // ✅ 绑定后台回调（FCM 会在合适时机触发）
  messaging.onBackgroundMessage(async (payload) => {
    try {
      await receiveBackgroundMessage(payload);
    } catch (e) {
      console.error('[SW] receiveBackgroundMessage error:', e);
    }
  });

  isFirebaseInitialized = true;
  console.log('[SW] Firebase initialized for messaging');
}

/* ------------------------------
 * 🧷 与页面通信
 * ------------------------------ */
async function sendToClients(type, data, options = {}) {
  const {
    sameOriginOnly = true,
  } = options;

  try {
    const clients = await self.clients.matchAll({ type: 'window', includeUncontrolled: true });
    for (const client of clients) {
      if (sameOriginOnly && !client.url.includes(self.location.origin)) continue;
      client.postMessage({ type, data });
    }
  } catch (e) {
    console.error('[SW] sendToClients failed:', e);
  }
  return true;
}

/* ------------------------------
 * 📨 统一的通知展示逻辑
 * ------------------------------ */
async function receiveBackgroundMessage(payload) {
  // 兼容 payload 结构：notification / data
  const data = payload?.data || payload?.notification?.data || {};
  const notification = payload?.notification || payload?.data || {};

  const title = notification.title || data.title || 'Notify';
  const body = notification.body || data.body || '';
  const image = notification.image || data.image || '/logo.png';

  const messageId = data.messageId || payload?.messageId || data?.mid;
  if (isDuplicate(messageId)) {
    // 避免双弹
    return;
  }

  // 1) 接收埋点
  await sendToClients(eventNameMap.notification_receive, data);

  // 2) 展示通知
  await self.registration.showNotification(title, {
    body,
    image,
    icon: image,
    data,
    tag: messageId || Date.now().toString(),
  });

  // 3) 展示埋点
  await sendToClients(eventNameMap.notification_display, data);
}

/* ------------------------------
 * 🔥 push 事件兜底（冷启动保险）
 * ------------------------------ */
self.addEventListener('push', (event) => {
  event.waitUntil((async () => {
    try {
      await ensureFirebaseReady();

      // 兜底：某些情况下 Firebase handler 不触发（或 payload 不是标准 FCM 格式）
      // 尝试解析 event.data 并触发统一通知逻辑
      if (event.data) {
        let payload = null;
        try {
          payload = event.data.json();
        } catch {
          const text = event.data.text();
          payload = { data: { body: text } };
        }

        // 只在 payload 看起来像通知时兜底显示，避免无意义弹窗
        const looksLikeNotification =
          payload?.notification ||
          payload?.data?.title ||
          payload?.data?.body ||
          payload?.data?.messageId;

        if (looksLikeNotification) {
          await receiveBackgroundMessage(payload);
        }
      }
    } catch (e) {
      console.error('[SW] push handler failed:', e);
      // 不 throw，避免浏览器将其视为未处理
    }
  })());
});

/* ------------------------------
 * 📤 前台请求展示通知（页面 postMessage）
 * ------------------------------ */
self.addEventListener('message', (event) => {
  if (event.data?.type !== 'SHOW_NOTIFICATION') return;

  event.waitUntil((async () => {
    try {
      const payload = event.data.payload || {};
      await receiveBackgroundMessage({ data: payload, notification: payload });
    } catch (e) {
      console.error('[SW] SHOW_NOTIFICATION failed:', e);
    }
  })());
});

/* ------------------------------
 * ❌ 通知关闭
 * ------------------------------ */
self.addEventListener('notificationclose', (event) => {
  event.waitUntil(sendToClients(eventNameMap.notification_dismiss, event.notification?.data));
});

/* ------------------------------
 * ✅ 通知点击：聚焦或打开窗口 + 埋点
 * ------------------------------ */
self.addEventListener('notificationclick', (event) => {
  event.notification.close();
  const messageData = event.notification?.data || {};

  event.waitUntil((async () => {
    // click 埋点
    await sendToClients(eventNameMap.notification_click, messageData);

    const clients = await self.clients.matchAll({ type: 'window', includeUncontrolled: true });

    // 优先聚焦已有页面（同源）
    for (const client of clients) {
      if (!client.url.includes(self.location.origin)) continue;
      if ('focus' in client) {
        await client.focus();
        // 通知页面 open 事件
        await sendToClients(eventNameMap.notification_open, messageData);
        return;
      }
    }

    // 没有页面则新开
    if (self.clients.openWindow) {
      const url = new URL(self.location.origin);
      if (messageData && typeof messageData === 'object') {
        Object.entries(messageData).forEach(([k, v]) => {
          if (v !== undefined && v !== null) url.searchParams.set(k, String(v));
        });
      }
      url.searchParams.set('fromNotification', 'true');
      await self.clients.openWindow(url.toString());
    }

    await sendToClients(eventNameMap.notification_open, messageData);
  })());
});