// ============================================================
// AppProvider — 全局应用状态 Context + Provider + Hook
//
// 导出：
//   AppContext, useAppContext()    — Context + Consumer Hook
//   AppContextValue                — 类型
//   AppProvider                    — Provider 组件
// ============================================================

import { createContext, useContext, useState, useMemo, useCallback, useEffect, type ReactNode } from 'react';
import type { Platform, Edition } from '@shared/types';

import { getPlatform, isDev } from '@/utils/platform';
import { safeIpcOn, safeIpcOff } from '@/utils/ipc';
import { AuthAPI, type LoginResponseBody } from '@/services/modules/auth';
import { setToken, clearToken, initTokenStore } from '@/services/request';
import { emit, EVENTS } from '@/utils/event-bus';
import { logger } from '@/utils/logger';
import { getAutoLoginFlag, clearAutoLoginFlag } from '@/services/auth-persistence';
import {
   initAuthRefresh,
   getStoredRefreshToken,
   setStoredRefreshToken,
   clearStoredRefreshToken,
   initRefreshTokenStore,
   scheduleProactiveRefresh,
   clearProactiveRefresh,
} from '@/services/auth-token';
import {initModelCache} from '@/services/cache/model-cache';

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

export interface AppContextValue {
   /** 当前操作系统平台 */
   platform: Platform;
   /** 产品版本（个人版 / 企业版） */
   edition: Edition;
   /** 用户是否已登录 */
   isLoggedIn: boolean;
   /** 当前登录用户信息（未登录时为 null，结构与 LoginResponseBody 一致） */
   user: LoginResponseBody | null;
   /** 登录：保存 Token 并更新登录态（auth 为登录接口返回值，异步加密存储） */
   login: (auth: LoginResponseBody) => Promise<void>;
   /** 退出登录：清除 Token 和用户状态 */
   logout: () => void;
   /** 是否为开发环境 */
   isDevMode: boolean;
}

export const AppContext = createContext<AppContextValue | null>(null);

// ---------- Consumer Hook ----------

export function useAppContext(): AppContextValue {
   const ctx = useContext(AppContext);
   if (!ctx) {
      throw new Error('useAppContext() 必须在 <AppProvider> 内部调用');
   }
   return ctx;
}

// ---------- Provider 组件 ----------

interface AppProviderProps {
   children: ReactNode;
}

export function AppProvider({ children }: AppProviderProps) {
   const [platform] = useState<Platform>(getPlatform);
   const [isLoggedIn, setIsLoggedIn] = useState(false);
   const [user, setUser] = useState<LoginResponseBody | null>(null);

   /**
    * edition 从登录用户的 account_type 派生（运行时判断，无需构建变量）
    *
    * 映射关系：
    *   "individual"                → personal  ← 个人用户
    *   "company" | "employee"      → enterprise ← 企业用户
    *   null（未登录）               → personal  ← 默认最小功能集
    *
    * 安全性：edition 是 useMemo 派生值，不可独立赋值；
    * 不写入 localStorage，重启/登出后回退默认值，必须重新登录才能确权。
    */
   const edition: Edition = useMemo(() => {
      if (!user) return 'personal';
      return user.account_type === 'individual' ? 'personal' : 'enterprise';
   }, [user]);

   // ---------- 登录 / 退出 ----------

   const login = useCallback(async (auth: LoginResponseBody) => {
      await setToken(auth.access_token);
      await setStoredRefreshToken(auth.refresh_token);
      // 启动主动刷新定时器（在 access_token 过期前自动续期）
      scheduleProactiveRefresh(auth.access_token);
      setUser(auth);
      setIsLoggedIn(true);
      logger.info('auth', 'User logged in', {
         userId: auth.user_id,
         username: auth.username,
      });
      emit(EVENTS.LOGIN_SUCCESS, auth);
   }, []);

   const logout = useCallback(() => {
      logger.info('auth', 'User logged out');
      clearToken();
      clearStoredRefreshToken();
      clearProactiveRefresh();
      setUser(null);
      setIsLoggedIn(false);
      emit(EVENTS.LOGOUT);
   }, []);

   // ---------- 启动时初始化 token 存储 + 自动登录 ----------
   //
   // 注意：React StrictMode（开发模式）会挂载→卸载→重新挂载以暴露副作用问题。
   // aborted 标志确保卸载后不再执行异步回调，避免 refreshToken / getUserInfo 重复请求。

   useEffect(() => {
      let aborted = false;

      // 从加密存储恢复 token + 模型缓存 到内存缓存
      Promise.all([initTokenStore(), initRefreshTokenStore(), initModelCache()]).then(() => {
         if (aborted) return;

         // 初始化 401 刷新回调（token 缓存就绪后才注册）
         initAuthRefresh();

         // 自动登录（refresh_token 续期）
         if (!getAutoLoginFlag()) return;

         const refreshToken = getStoredRefreshToken();
         if (!refreshToken) return;

         AuthAPI.refreshToken({ refresh_token: refreshToken })
            .then(async (res) => {
               if (aborted) return;
               await setToken(res.access_token);
               await setStoredRefreshToken(res.refresh_token);
               scheduleProactiveRefresh(res.access_token);
               setIsLoggedIn(true);
               logger.info('auth', 'Auto-login succeeded');
               // 补全用户信息
               AuthAPI.getUserInfo().then((info) => {
                  if (aborted) return;
                  const u: LoginResponseBody = {
                     access_token: res.access_token,
                     refresh_token: res.refresh_token,
                     token_type: res.token_type,
                     expires_in: res.expires_in,
                     refresh_expires_in: res.refresh_expires_in,
                     user_id: info.id,
                     username: info.username,
                     role: info.role,
                     email: info.email ?? '',
                     balance_cent: info.balance_cent,
                     account_type: info.account_type,
                     display_name: info.display_name ?? '',
                     company_id: info.company_id ?? '',
                     real_name: info.real_name ?? '',
                     phone: info.phone,
                     license_code: '',
                     admin_permissions: info.admin_permissions ?? [],
                  };
                  setUser(u);
                  emit(EVENTS.LOGIN_SUCCESS, u);
               });
            })
            .catch(() => {
               if (aborted) return;
               logger.warn('auth', 'Auto-login failed, refresh_token expired');
               clearStoredRefreshToken();
               // 仅清除自动登录标记，保留用户名供下次表单回填
               clearAutoLoginFlag();
            });
      });

      return () => { aborted = true; };
   }, []);

   // ---------- 监听主进程推送的平台/版本信息 ----------

   useEffect(() => {
      const handler = (_event: unknown, info: unknown) => {
         const data = info as { platform?: string; edition?: string } | undefined;
         if (data) {
            logger.debug('app', 'Received platform info from main process', data as Record<string, unknown>);
         }
      };
      safeIpcOn('platform-info', handler);
      return () => {
         safeIpcOff('platform-info', handler);
      };
   }, []);

   const value: AppContextValue = {
      platform,
      edition,
      isLoggedIn,
      user,
      login,
      logout,
      isDevMode: isDev(),
   };

   return <AppContext.Provider value={value}>{children}</AppContext.Provider>;
}
