// ============================================================
// safe-storage — 渲染进程安全存储工具
//
// 架构：
//   - 内存缓存：get() 同步返回，避免每次 API 请求都触发 IPC 往返
//   - 持久化：set() 异步加密后写入 localStorage
//   - 启动恢复：init() 从 localStorage 读取密文，异步解密到内存缓存
//   - 降级：非 Electron 环境回退到 localStorage 明文（仅开发用）
//
// 使用模式：
//   // App 启动时
//   await safeStore.init('my-key');
//
//   // 任意位置读取（同步，高频安全）
//   const value = safeStore.get('my-key');
//
//   // 写入（异步加密）
//   await safeStore.set('my-key', 'plaintext');
//
//   // 清除
//   safeStore.clear('my-key');
// ============================================================

import { hasIpc, logger } from './bus';

// ---------- 内部状态 ----------

/** 内存缓存（key → 明文） */
const cache = new Map<string, string>();

// ---------- IPC 桥接 ----------

interface SafeStorageBridge {
   encrypt(plaintext: string): Promise<string | null>;
   decrypt(encryptedBase64: string): Promise<string | null>;
}

/** 获取 safeStorage 桥接（由 preload 注入） */
function getBridge(): SafeStorageBridge | null {
   if (!hasIpc() || !window.safeStorage) return null;
   return window.safeStorage;
}

// ---------- 公开 API ----------

/**
 * 初始化指定的键：从持久化存储读取密文 → 解密 → 加载到内存缓存。
 * 应在 App 启动时（如 AppProvider 挂载）对需要用到的 key 逐一调用。
 *
 * @param key - 存储键名（与 localStorage key 对应）
 * @returns 解密后的明文，失败或无数据返回 null
 */
export async function initSafeStore(key: string): Promise<string | null> {
   // 先从 localStorage 读取密文
   let encrypted: string | null = null;
   try {
      encrypted = localStorage.getItem(key);
   } catch (err) {
      logger.warn('safe-storage', `初始化 ${key} 时读取 localStorage 失败`, err instanceof Error ? err : undefined);
      return null;
   }
   if (!encrypted) return null;

   const bridge = getBridge();

   if (bridge) {
      // Electron 环境：IPC 解密
      const plaintext = await bridge.decrypt(encrypted);
      if (plaintext !== null) {
         cache.set(key, plaintext);
         return plaintext;
      }
      // 解密失败（可能 OS 密钥变更）→ 清除残留
      logger.warn('safe-storage', `解密 ${key} 失败（可能 OS 密钥变更），清除残留数据`);
      try {
         localStorage.removeItem(key);
      } catch {
         /* 静默 */
      }
      return null;
   }

   // 非 Electron 环境（浏览器开发）：localStorage 明文
   cache.set(key, encrypted);
   return encrypted;
}

/**
 * 同步读取已缓存的明文（高频安全，不触发 IPC）。
 * 如果缓存未命中，返回 null（调用方应先 await initSafeStore）。
 */
export function getSafeStore(key: string): string | null {
   return cache.get(key) ?? null;
}

/**
 * 加密并持久化存储。
 * 同时更新内存缓存（后续 get() 可直接同步读取）。
 *
 * @returns 是否存储成功
 */
export async function setSafeStore(key: string, plaintext: string): Promise<boolean> {
   // 先更新内存缓存（即使持久化失败，当前 session 仍可用）
   cache.set(key, plaintext);

   const bridge = getBridge();

   if (bridge) {
      // Electron 环境：加密后写入 localStorage
      const encrypted = await bridge.encrypt(plaintext);
      if (encrypted !== null) {
         try {
            localStorage.setItem(key, encrypted);
            return true;
         } catch (err) {
            logger.warn('safe-storage', `加密写入 ${key} 到 localStorage 失败`, err instanceof Error ? err : undefined);
            return false;
         }
      }
      logger.warn('safe-storage', `加密 ${key} 失败（safeStorage.encrypt 返回 null）`);
      return false;
   }

   // 非 Electron 环境：直接写入 localStorage 明文
   try {
      localStorage.setItem(key, plaintext);
      return true;
   } catch (err) {
      logger.warn('safe-storage', `明文写入 ${key} 到 localStorage 失败`, err instanceof Error ? err : undefined);
      return false;
   }
}

/**
 * 清除指定键的缓存和持久化数据。
 * 同步执行（不阻塞），持久化清除为 best-effort。
 */
export function clearSafeStore(key: string): void {
   cache.delete(key);
   try {
      localStorage.removeItem(key);
   } catch {
      /* 静默 */
   }
}

/**
 * 检查指定键是否已有缓存（用于判断 init 是否已被调用）。
 */
export function hasSafeStoreCache(key: string): boolean {
   return cache.has(key);
}
