/**
 * 桌面端（Electron）能力封装
 * 桌面端由 apps/desktop 的 preload 脚本注入 window.desktopAPI；
 * 浏览器环境没有该对象，本封装的所有方法自动 no-op 降级，保证网页端行为完全不变。
 * 业务代码禁止直接访问 window.desktopAPI，统一走本文件，便于类型收敛与降级兜底。
 */

/** 系统打印机信息（Electron getPrintersAsync 的子集） */
export interface DesktopPrinter {
  name: string;
  displayName: string;
  isDefault: boolean;
}

/** 桌面端本地设置（与 apps/desktop 主进程 settings.ts 保持同步） */
export interface DesktopSettings {
  /** 静默打印使用的打印机名称，空串表示系统默认打印机 */
  printerName: string;
  /** 是否启用静默打印 */
  silentPrint: boolean;
}

/** 自动更新事件（主进程 updater 转发，渲染层做轻量提示） */
export interface DesktopUpdateEvent {
  type: 'available' | 'downloaded' | 'error' | 'not-available' | 'progress';
  data?: unknown;
}

/** 判断当前是否运行在 Electron 桌面端 */
export function isElectron(): boolean {
  return typeof window !== 'undefined' && !!window.desktopAPI?.isElectron;
}

/** 取桥接 API：浏览器环境返回 undefined，调用方全部可选链降级 */
function api() {
  return typeof window === 'undefined' ? undefined : window.desktopAPI;
}

// onNavigate / onUpdateEvent 的桥接层每调用一次就会新增一个 ipc 监听，
// 而布局组件会随登录/登出反复挂载。这里用「模块级单次桥接 + 可替换回调」避免监听器堆积
let navigateCallback: ((route: string) => void) | null = null;
let navigateBridged = false;
let updateCallback: ((payload: DesktopUpdateEvent) => void) | null = null;
let updateBridged = false;

export const desktop = {
  /** 发送系统通知；route 为点击通知后要跳转的前端路由（不传则仅唤起窗口） */
  notify(options: { body: string; route?: string; title: string }): void {
    api()?.notify(options);
  },
  /** 设置未读角标数量，0 表示清除（mac Dock 数字 / Windows 任务栏覆盖图标） */
  setBadge(count: number): void {
    api()?.setBadge(count);
  },
  /** 任务栏闪烁提醒（窗口未聚焦时生效，聚焦后自动清除） */
  flashFrame(): void {
    api()?.flashFrame();
  },
  /** 读取开机自启状态（浏览器环境恒为 false） */
  async getAutoLaunch(): Promise<boolean> {
    return (await api()?.getAutoLaunch()) ?? false;
  },
  /** 设置开机自启，返回设置后的实际状态 */
  async setAutoLaunch(enable: boolean): Promise<boolean> {
    return (await api()?.setAutoLaunch(enable)) ?? false;
  },
  /** 获取系统打印机列表（浏览器环境返回空数组） */
  async getPrinters(): Promise<DesktopPrinter[]> {
    return (await api()?.getPrinters()) ?? [];
  },
  /** 静默打印：传入拼好的完整 HTML，由主进程隐藏窗口出纸 */
  async printHTML(options: {
    deviceName?: string;
    html: string;
    silent?: boolean;
  }): Promise<{ message?: string; ok: boolean }> {
    return (
      (await api()?.printHTML(options)) ?? {
        ok: false,
        message: '当前环境不支持桌面打印',
      }
    );
  },
  /** 读取桌面端设置 */
  async getSettings(): Promise<DesktopSettings> {
    return (await api()?.getSettings()) ?? { printerName: '', silentPrint: false };
  },
  /** 增量更新桌面端设置，返回更新后的完整设置 */
  async setSettings(patch: Partial<DesktopSettings>): Promise<DesktopSettings> {
    return (
      (await api()?.setSettings(patch)) ?? { printerName: '', silentPrint: false }
    );
  },
  /** 手动检查更新（结果由主进程弹窗反馈） */
  checkUpdate(): void {
    api()?.checkUpdate();
  },
  /** 唤起并聚焦主窗口 */
  focusWindow(): void {
    api()?.focusWindow();
  },
  /** 监听系统通知点击后的路由跳转请求（重复调用只替换回调，不会堆积监听器） */
  onNavigate(callback: (route: string) => void): void {
    navigateCallback = callback;
    if (!navigateBridged && api()) {
      navigateBridged = true;
      api()!.onNavigate((route) => navigateCallback?.(route));
    }
  },
  /** 解绑路由跳转回调：布局卸载（登出）时调用，避免残留系统通知被点击后对已登出会话执行跳转 */
  offNavigate(): void {
    navigateCallback = null;
  },
  /** 监听自动更新事件（重复调用只替换回调，不会堆积监听器） */
  onUpdateEvent(callback: (payload: DesktopUpdateEvent) => void): void {
    updateCallback = callback;
    if (!updateBridged && api()) {
      updateBridged = true;
      api()!.onUpdateEvent((payload) => updateCallback?.(payload as DesktopUpdateEvent));
    }
  },
};
