// ============================================================
// useUpdater — 渲染进程中的更新状态管理（单例 IPC 监听）
//
// 用法：
//   const { status, progress, checkForUpdates, installUpdate } = useUpdater();
//
// 状态机：idle → checking → (no-update | available → downloading → downloaded → idle)
//
// 关键设计：
//   - IPC 监听器在模块级别只注册一次（单例），避免多个组件同时
//     调用 useUpdater() 导致 MaxListenersExceededWarning
//   - 所有 useUpdater() 实例通过订阅机制共享同一份状态
// ============================================================

import { useState, useEffect, useCallback, useRef } from 'react';

import { safeIpcInvoke, safeIpcOn, safeIpcSend, logger } from '@/shared/utils/bus';

// ---------- 类型 ----------

export type UpdaterStatus =
   | 'idle'
   | 'checking'
   | 'no-update'
   | 'available'
   | 'downloading'
   | 'downloaded'
   | 'error';

export interface UpdateInfo {
   version: string;
   releaseDate?: string;
   releaseNotes?: string;
   forceUpdate?: boolean;
}

export interface UpdateProgress {
   percent: number;
   bytesPerSecond?: number;
   transferred?: number;
   total?: number;
}

export interface UpdateError {
   message: string;
}

// ---------- 模块级共享状态 ----------

interface UpdaterState {
   status: UpdaterStatus;
   info: UpdateInfo | null;
   progress: UpdateProgress;
   error: UpdateError | null;
}

type Subscriber = (state: UpdaterState) => void;

let sharedState: UpdaterState = {
   status: 'idle',
   info: null,
   progress: { percent: 0 },
   error: null,
};

const subscribers = new Set<Subscriber>();
let listenersRegistered = false;

function notifyAll(): void {
   const snapshot = { ...sharedState };
   subscribers.forEach((fn) => {
      try {
         fn(snapshot);
      } catch {
         /* 单个订阅者异常不影响其他 */
      }
   });
}

function setSharedState(patch: Partial<UpdaterState>): void {
   sharedState = { ...sharedState, ...patch };
   notifyAll();
}

// ---------- IPC 通道名（与主进程 updater.ts 保持一致）----------

const CH = {
   UPDATE_AVAILABLE: 'update-available',
   UPDATE_PROGRESS: 'update-progress',
   UPDATE_DOWNLOADED: 'update-downloaded',
   UPDATE_ERROR: 'update-error',
   UPDATE_NOT_AVAILABLE: 'update-not-available',
   INSTALL_UPDATE: 'install-update',
   CHECK_FOR_UPDATE: 'check-for-update',
   DOWNLOAD_UPDATE: 'download-update',
} as const;

// ---------- 注册 IPC 监听器（模块级，仅一次）----------

function ensureListeners(): void {
   if (listenersRegistered) return;
   listenersRegistered = true;

   safeIpcOn(CH.UPDATE_AVAILABLE, (_event: unknown, ...args: unknown[]) => {
      setSharedState({ info: args[0] as UpdateInfo, status: 'available' });
   });

   safeIpcOn(CH.UPDATE_PROGRESS, (_event: unknown, ...args: unknown[]) => {
      setSharedState({ status: 'downloading', progress: args[0] as UpdateProgress });
   });

   safeIpcOn(CH.UPDATE_DOWNLOADED, () => {
      setSharedState({ status: 'downloaded' });
   });

   safeIpcOn(CH.UPDATE_ERROR, (_event: unknown, ...args: unknown[]) => {
      setSharedState({ error: args[0] as UpdateError, status: 'error' });
   });

   safeIpcOn(CH.UPDATE_NOT_AVAILABLE, () => {
      setSharedState({ status: 'no-update' });
   });
}

// ---------- Hook ----------

export function useUpdater() {
   const [state, setState] = useState<UpdaterState>(sharedState);
   const subscribed = useRef(false);

   // 确保 IPC 监听器只注册一次
   useEffect(() => {
      ensureListeners();
   }, []);

   // 订阅模块级状态变更
   useEffect(() => {
      if (subscribed.current) return;
      subscribed.current = true;

      const sub: Subscriber = (newState) => setState(newState);
      subscribers.add(sub);

      return () => {
         subscribers.delete(sub);
         subscribed.current = false;
      };
   }, []);

   // 同步初始状态（防止在订阅之前状态已变更）
   useEffect(() => {
      setState(sharedState);
   }, []);

   /** 手动检查更新 */
   const checkForUpdates = useCallback(async () => {
      console.log("process.env.UPDATE_API_URL:", process.env.UPDATE_API_URL);
      setSharedState({ status: 'checking', error: null });
      try {
         await safeIpcInvoke(CH.CHECK_FOR_UPDATE);
      } catch (err) {
         logger.warn('updater', '检查更新失败', err instanceof Error ? err : new Error(String(err)));
         setSharedState({
            status: 'error',
            error: { message: (err as Error).message || '检查更新失败' },
         });
      }
   }, []);

   /** 用户确认后开始下载更新 */
   const downloadUpdate = useCallback(async () => {
      setSharedState({ status: 'downloading', error: null });
      try {
         await safeIpcInvoke(CH.DOWNLOAD_UPDATE);
      } catch (err) {
         logger.warn('updater', '下载更新失败', err instanceof Error ? err : new Error(String(err)));
         setSharedState({
            status: 'error',
            error: { message: (err as Error).message || '下载更新失败' },
         });
      }
   }, []);

   /** 确认安装更新（退出 → 安装 → 重启） */
   const installUpdate = useCallback(() => {
      safeIpcSend(CH.INSTALL_UPDATE);
   }, []);

   /** 重置状态 */
   const reset = useCallback(() => {
      setSharedState({
         status: 'idle',
         info: null,
         progress: { percent: 0 },
         error: null,
      });
   }, []);

   return {
      status: state.status,
      info: state.info,
      progress: state.progress,
      error: state.error,
      checkForUpdates,
      downloadUpdate,
      installUpdate,
      reset,
   } as const;
}
