/**
 * Auth Store - Zustand + Tauri 原生文件存储
 * ==========================================
 *
 * 认证状态持久化到 Tauri 原生文件存储
 * 路径：应用配置目录 / auth.json
 *
 * 迁移：首次运行自动从 localStorage 迁移，迁移成功后删除旧数据
 */

import { create } from 'zustand';
import { invoke } from '@tauri-apps/api/core';
import { getVersion } from '@tauri-apps/api/app';
import { client, clearAuthCache, PYTHON_API_BASE_URL, setOnTokenRefreshed, setOnAuthFailed } from '../api/client';
import { isTauri } from '../utils/env';
// uiStore 不再直接导入，弹窗由 React 组件通过状态驱动渲染

interface UserInfo {
  id: string;
  nickname: string;
  avatar: string;
}

interface AuthState {
  isAuthenticated: boolean;
  accessToken: string | null;
  refreshToken: string | null;
  user: UserInfo | null;
  isLoading: boolean;
  showKickModal: boolean;
  kickMessage: string;
}

interface AuthActions {
  login: (_phone: string, _code: string) => Promise<void>;
  logout: () => Promise<void>;
  checkAuth: () => boolean;
  loadFromStorage: () => Promise<void>;
  closeKickModal: () => void;
}
 

type AuthStore = AuthState & AuthActions;

const initialState: AuthState = {
  isAuthenticated: false,
  accessToken: null,
  refreshToken: null,
  user: null,
  isLoading: true,
  showKickModal: false,
  kickMessage: '',
};

const AUTH_LOCAL_STORAGE_KEY = 'ai-video-auth';

// 登录防重入标志
let isLoggingIn = false;

// SSE 连接（模块级，不放入 Zustand state，因为 EventSource 不可序列化）
let _sseConnection: EventSource | null = null;

function connectSSE(accessToken: string) {
  disconnectSSE();
  if (!accessToken || !PYTHON_API_BASE_URL) {return;}

  const url = `${PYTHON_API_BASE_URL}/events?token=${encodeURIComponent(accessToken)}`;
  const es = new EventSource(url);

  es.onmessage = (event) => {
    try {
      const data = JSON.parse(event.data);
      if (data.type === 'kick') {
        const state = useAuthStore.getState();
        if (!state.isAuthenticated || state.showKickModal) {return;}
        // 先弹窗，不清除状态；用户点击确认后再清除
        useAuthStore.setState({
          showKickModal: true,
          kickMessage: '当前账号在其他设备登录，即将退出',
        });
      }
    } catch (e) {
      console.error('[SSE] 消息解析失败:', e);
    }
  };

  es.onerror = () => {
    console.error('[SSE] 连接错误，3秒后尝试重连');
    es.close();
    _sseConnection = null;
    setTimeout(() => {
      const { accessToken: currentToken } = useAuthStore.getState();
      if (currentToken) {connectSSE(currentToken);}
    }, 3000);
  };

  _sseConnection = es;
}

function disconnectSSE() {
  if (_sseConnection) {
    _sseConnection.close();
    _sseConnection = null;
  }
}

/**
 * 清理本地认证状态（被踢或 Token 失效时调用，不通知后端）
 */
async function clearAuthState(): Promise<void> {
  disconnectSSE();
  clearAuthCache();
  if (isTauri()) {
    await invoke('clear_auth_state').catch(() => {});
  } else {
    localStorage.removeItem(AUTH_LOCAL_STORAGE_KEY);
  }
}

/**
 * 保存认证状态（Tauri 文件存储优先，浏览器回退 localStorage）
 */
async function saveAuthState(state: AuthState): Promise<void> {
  const payload = {
    isAuthenticated: state.isAuthenticated,
    accessToken: state.accessToken,
    refreshToken: state.refreshToken,
    user: state.user,
  };
  if (isTauri()) {
    await invoke('save_auth_state', { state: payload });
  } else {
    localStorage.setItem(AUTH_LOCAL_STORAGE_KEY, JSON.stringify({ state: payload }));
  }
}

// 生成设备 ID（device_id 保持在 localStorage，因为它不需要太大空间
const generateDeviceId = () => {
  const stored = localStorage.getItem('device_id');
  if (stored) {
    return stored;
  }
  const newId = `web_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  localStorage.setItem('device_id', newId);
  return newId;
};

// 缓存应用版本号，避免每次登录都调用 IPC
let appVersionCache: string | null = null;

async function getAppVersion(): Promise<string> {
  if (appVersionCache) {
    return appVersionCache;
  }
  try {
    appVersionCache = await getVersion();
  } catch {
    appVersionCache = 'unknown';
  }
  return appVersionCache;
}

// 注册 Token 刷新回调：client.ts 的 doRefreshToken 成功后会触发此回调，
// 确保新 Token 被持久化到 Tauri 文件存储 / localStorage
setOnTokenRefreshed((tokens) => {
  const state = useAuthStore.getState();
  if (state.isAuthenticated) {
    const newState: AuthState = {
      ...state,
      accessToken: tokens.accessToken,
      refreshToken: tokens.refreshToken,
    };
    useAuthStore.setState(newState);
    saveAuthState(newState).catch((e) => console.error('[authStore] 保存刷新后的 Token 失败:', e));
  }
});

// 注册认证失效回调：Refresh Token 失效（401 设备已失效）时先弹窗
// 注意：不能调用 logout()，因为 logout() 内部会请求 /auth/logout，又可能触发 401 循环
setOnAuthFailed(() => {
  const state = useAuthStore.getState();
  if (!state.isAuthenticated || state.showKickModal) {return;}
  // 先弹窗，不清除状态；用户点击确认后再清除
  useAuthStore.setState({
    showKickModal: true,
    kickMessage: '当前账号在其他设备登录，即将退出',
  });
});

export const useAuthStore = create<AuthStore>((set, get) => ({
  ...initialState,

  /**
   * 从存储加载认证状态（Tauri 文件存储优先，浏览器回退 localStorage）
   */
  loadFromStorage: async () => {
    set({ isLoading: true });

    try {
      if (!isTauri()) {
        // 浏览器环境：回退到 localStorage
        const data = localStorage.getItem(AUTH_LOCAL_STORAGE_KEY);
        if (data) {
          const parsed = JSON.parse(data);
          const state = parsed.state as AuthState | undefined;
          if (state?.isAuthenticated && state.accessToken) {
            set({ ...initialState, ...state, isLoading: false });
            // 浏览器环境重连 SSE
            connectSSE(state.accessToken);
            return;
          }
        }
        set({ ...initialState, isLoading: false });
        return;
      }

      // Tauri 环境：从原生文件加载
      const result = await invoke<{ code: number; data?: AuthState }>('load_auth_state');
      if (result.code === 200 && result.data) {
        const loadedState: AuthState = {
          ...initialState,
          isAuthenticated: result.data.isAuthenticated ?? false,
          accessToken: result.data.accessToken ?? null,
          refreshToken: result.data.refreshToken ?? null,
          user: result.data.user ?? null,
          isLoading: false,
        };
        set(loadedState);
        clearAuthCache();
        // 若已登录，重连 SSE 以接收单设备踢人通知
        if (loadedState.isAuthenticated && loadedState.accessToken) {
          connectSSE(loadedState.accessToken);
        }
      } else {
        set({ ...initialState, isLoading: false });
      }
    } catch (e) {
      console.error('[authStore] 加载认证状态失败:', e);
      set({ ...initialState, isLoading: false });
    }
  },

  // 手机号验证码登录
  login: async (phone: string, code: string) => {
    if (isLoggingIn) {return;}
    isLoggingIn = true;

    try {
      const data = await client.post<{ accessToken: string; refreshToken: string; user: UserInfo }>('/auth/login', {
        mobile: phone,
        code,
        deviceId: generateDeviceId(),
        deviceName: '美家卡智影桌面端',
        osInfo: navigator.userAgent,
        appVersion: await getAppVersion(),
      });

      const newState = {
        isAuthenticated: true,
        accessToken: data.accessToken,
        refreshToken: data.refreshToken,
        user: data.user,
        isLoading: false,
        showKickModal: false,
        kickMessage: '',
      };

      set(newState);
      await saveAuthState(newState);
      clearAuthCache();
      connectSSE(data.accessToken);
    } catch (error) {
      console.error('[authStore] 登录失败:', error);
      isLoggingIn = false;
      throw error;
    } finally {
      isLoggingIn = false;
    }
  },

  closeKickModal: () => {
    clearAuthState();
    set({ ...initialState, isLoading: false, showKickModal: false, kickMessage: '' });
  },

  logout: async () => {
    // 断开 SSE 连接
    disconnectSSE();

    // 先调用后端登出 API（清理设备记录）
    try {
      await client.post('/auth/logout');
    } catch {
      // 后端登出失败不影响前端状态清理
    }

    // 重置状态
    set({ ...initialState, isLoading: false });
    // 清除内存缓存
    clearAuthCache();
    // 清除存储中的认证数据
    try {
      if (isTauri()) {
        await invoke('clear_auth_state');
      } else {
        localStorage.removeItem(AUTH_LOCAL_STORAGE_KEY);
      }
    } catch (e) {
      console.error('[Auth] 清除认证状态失败:', e);
    }
  },

  checkAuth: () => {
    const { isAuthenticated, accessToken } = get();
    return isAuthenticated && !!accessToken;
  },
}));
