/* localStorage / sessionStorage helpers + 雲端同步
 *
 * window.usePersistedState(key, default, opts?)
 *   - 自動偵測 key 是否在 CLOUD_KEYS 白名單，若是則啟用 Firestore 雙向同步
 *   - opts.forceCloud = true → 強制 cloud sync（給 useCloudState 用）
 *   - Cloud snapshot 與 setValue 都 mirror 到 localStorage，斷網仍能讀
 *
 * window.useCloudState(key, default)  ←  強制 cloud sync 版（alias）
 *
 * window.TWStorage = { get, set, remove }  純 localStorage 同步介面
 *
 * Key 命名：一律以 "twstock." 開頭。
 *
 * CLOUD_KEYS 是「跨裝置該一致」的設定（API token、Worker URL、通知規則、
 * 觀察清單、繪圖痕跡等）。UI 偏好（activeId、toggles 等）刻意留本地，
 * 讓不同裝置可以有不同視角。
 */

const PREFIX = "twstock.";
const CLOUD_COLLECTION = "userState";

const CLOUD_KEYS = new Set([
  "watchlists",
  "alert.rules",
  "telegram.chatId",
  "finmind.token",
  "intraday.workerUrl",
  "intraday.auth",
  "chart.drawings",
]);

function safeGet(key) {
  try {
    const raw = localStorage.getItem(PREFIX + key);
    return raw == null ? undefined : JSON.parse(raw);
  } catch (e) {
    console.warn("[storage] get failed", key, e);
    return undefined;
  }
}

function safeSet(key, value) {
  try {
    localStorage.setItem(PREFIX + key, JSON.stringify(value));
    return true;
  } catch (e) {
    console.warn("[storage] set failed", key, e);
    return false;
  }
}

function safeRemove(key) {
  try { localStorage.removeItem(PREFIX + key); } catch (e) {}
}

function getFirestore() {
  try { return window.firebase && window.firebase.firestore && window.firebase.firestore(); }
  catch (e) { return null; }
}

function usePersistedState(key, defaultValue, opts = {}) {
  const forceCloud = !!opts.forceCloud;
  const shouldCloud = forceCloud || CLOUD_KEYS.has(key);

  const [value, _setValue] = React.useState(() => {
    const stored = safeGet(key);
    return stored === undefined ? defaultValue : stored;
  });
  const [user, setUser] = React.useState(() => {
    try { return window.firebase?.auth?.().currentUser || null; } catch (e) { return null; }
  });

  /* Auth state — 僅 cloud key 需要 */
  React.useEffect(() => {
    if (!shouldCloud) return;
    if (!window.firebase || !window.firebase.auth) return;
    let unsub;
    try { unsub = window.firebase.auth().onAuthStateChanged((u) => setUser(u)); }
    catch (e) { console.warn("[storage] auth not ready", e.message); }
    return () => { if (unsub) unsub(); };
  }, [shouldCloud]);

  /* Cloud subscribe + 首次遷移 */
  React.useEffect(() => {
    if (!shouldCloud || !user) return;
    const db = getFirestore();
    if (!db) return;
    const ref = db.collection(CLOUD_COLLECTION).doc(user.uid);

    let cancelled = false;
    (async () => {
      try {
        const snap = await ref.get();
        if (cancelled) return;
        const cloud = snap.exists ? snap.data() : null;
        if (cloud && cloud[key] !== undefined) {
          _setValue(cloud[key]);
          safeSet(key, cloud[key]);
        } else {
          const local = safeGet(key);
          if (local !== undefined) {
            await ref.set({
              [key]: local,
              updatedAt: window.firebase.firestore.FieldValue.serverTimestamp(),
            }, { merge: true });
          }
        }
      } catch (e) {
        console.warn("[storage] cloud sync init failed", key, e.message);
      }
    })();

    const unsub = ref.onSnapshot({ includeMetadataChanges: true }, (snap) => {
      /* 自家寫入會先以 pending 觸發，跳過避免 echo */
      if (snap.metadata.hasPendingWrites) return;
      const data = snap.data();
      if (!data || data[key] === undefined) return;
      _setValue(data[key]);
      safeSet(key, data[key]);
    }, (e) => console.warn("[storage] snapshot error", key, e.message));

    return () => { cancelled = true; unsub(); };
  }, [shouldCloud, user?.uid, key]);

  /* 本地 mirror */
  React.useEffect(() => { safeSet(key, value); }, [key, value]);

  const setValue = React.useCallback((updater) => {
    _setValue((prev) => {
      const next = typeof updater === "function" ? updater(prev) : updater;
      safeSet(key, next);
      /* 觀察清單一變更就通知 alert 排程自動同步到 worker KV（解耦：storage 不直接依賴 Intraday） */
      if (key === "watchlists" && typeof window !== "undefined") {
        window.dispatchEvent(new CustomEvent("twstock:watchlists-changed"));
      }
      if (shouldCloud && user) {
        const db = getFirestore();
        if (db) {
          db.collection(CLOUD_COLLECTION).doc(user.uid).set({
            [key]: next,
            updatedAt: window.firebase.firestore.FieldValue.serverTimestamp(),
          }, { merge: true }).catch((e) => console.warn("[storage] cloud write failed", key, e.message));
        }
      }
      return next;
    });
  }, [shouldCloud, user, key]);

  return [value, setValue];
}

window.TWStorage = { get: safeGet, set: safeSet, remove: safeRemove };
window.usePersistedState = usePersistedState;
window.useCloudState = (key, defaultValue) => usePersistedState(key, defaultValue, { forceCloud: true });
window.CLOUD_KEYS = CLOUD_KEYS;
