/**
 * Tauri 自动更新 Hook
 * ===================
 *
 * 封装 Tauri updater 插件的 check / download / install / relaunch 流程。
 */

import { useState, useCallback, useRef } from 'react';
import { check, type Update, type DownloadEvent } from '@tauri-apps/plugin-updater';
import { relaunch } from '@tauri-apps/plugin-process';

export interface UpdaterState {
  /** 是否有可用更新 */
  hasUpdate: boolean;
  /** 更新信息 */
  updateInfo: Update | null;
  /** 是否强制更新 */
  isMandatory: boolean;
  /** 是否正在检查 */
  checking: boolean;
  /** 是否正在下载 */
  downloading: boolean;
  /** 是否正在安装 */
  installing: boolean;
  /** 下载进度（0-100） */
  progress: number;
  /** 已下载字节数 */
  downloadedBytes: number;
  /** 总字节数 */
  totalBytes: number;
  /** 错误信息 */
  error: string | null;
}

export interface UpdaterActions {
  /** 检查更新 */
  check: (silent?: boolean) => Promise<void>;
  /** 下载并安装 */
  downloadAndInstall: () => Promise<void>;
  /** 忽略本次更新 */
  dismiss: () => void;
  /** 重启应用 */
  relaunch: () => Promise<void>;
}

/**
 * 解析更新说明中的强制更新标记
 * 如果 notes 中包含 [强制更新] 或 [mandatory]，视为强制更新
 */
function parseMandatory(notes: string | undefined): boolean {
  if (!notes) {return false;}
  return notes.includes('[强制更新]') || notes.includes('[mandatory]');
}

export function useUpdater(): UpdaterState & UpdaterActions {
  const [state, setState] = useState<UpdaterState>({
    hasUpdate: false,
    updateInfo: null,
    isMandatory: false,
    checking: false,
    downloading: false,
    installing: false,
    progress: 0,
    downloadedBytes: 0,
    totalBytes: 0,
    error: null,
  });

  // 用 ref 保存 update 实例，避免闭包问题
  const updateRef = useRef<Update | null>(null);

  const checkUpdate = useCallback(async (silent: boolean = false) => {
    setState(s => ({ ...s, checking: true, error: null }));

    try {
      const update = await check();
      updateRef.current = update ?? null;

      if (update) {
        const mandatory = parseMandatory(update.body ?? undefined);
        setState(s => ({
          ...s,
          hasUpdate: true,
          updateInfo: update,
          isMandatory: mandatory,
          checking: false,
        }));
      } else {
        setState(s => ({
          ...s,
          hasUpdate: false,
          updateInfo: null,
          isMandatory: false,
          checking: false,
        }));
      }
    } catch (err) {
      console.error('[useUpdater] 检查更新失败:', err);
      setState(s => ({
        ...s,
        hasUpdate: false,
        checking: false,
        error: silent ? null : (err instanceof Error ? err.message : '检查更新失败'),
      }));
    }
  }, []);

  const downloadAndInstall = useCallback(async () => {
    const update = updateRef.current;
    if (!update) {return;}

    setState(s => ({
      ...s,
      downloading: true,
      installing: false,
      progress: 0,
      downloadedBytes: 0,
      totalBytes: 0,
      error: null,
    }));

    try {
      await update.downloadAndInstall((event: DownloadEvent) => {
        switch (event.event) {
          case 'Started':
            setState(s => ({
              ...s,
              totalBytes: event.data.contentLength ?? 0,
            }));
            break;
          case 'Progress':
            setState(s => {
              const downloaded = s.downloadedBytes + event.data.chunkLength;
              const total = s.totalBytes;
              const progress = total > 0 ? Math.round((downloaded / total) * 100) : 0;
              return {
                ...s,
                downloadedBytes: downloaded,
                progress: Math.min(progress, 100),
              };
            });
            break;
          case 'Finished':
            setState(s => ({ ...s, progress: 100 }));
            break;
        }
      });

      setState(s => ({
        ...s,
        downloading: false,
        installing: true,
      }));
    } catch (err) {
      console.error('[useUpdater] 下载安装失败:', err);
      setState(s => ({
        ...s,
        downloading: false,
        installing: false,
        error: err instanceof Error ? err.message : '下载安装失败',
      }));
    }
  }, []);

  const dismiss = useCallback(() => {
    updateRef.current = null;
    setState({
      hasUpdate: false,
      updateInfo: null,
      isMandatory: false,
      checking: false,
      downloading: false,
      installing: false,
      progress: 0,
      downloadedBytes: 0,
      totalBytes: 0,
      error: null,
    });
  }, []);

  const doRelaunch = useCallback(async () => {
    try {
      await relaunch();
    } catch (err) {
      console.error('[useUpdater] 重启失败:', err);
      setState(s => ({
        ...s,
        error: err instanceof Error ? err.message : '重启失败',
      }));
    }
  }, []);

  return {
    ...state,
    check: checkUpdate,
    downloadAndInstall,
    dismiss,
    relaunch: doRelaunch,
  };
}
