import type { LoginRequest, SysUser } from '@/service/types'
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
import {
  authLoginUsingPost,
  authProfileUsingGet,
  authRefreshUsingPost,
} from '@/service'
import { toast } from '@/utils/toast'

/**
 * 用户状态管理
 * 管理用户登录状态、个人信息、令牌管理等
 */
export const useUserStore = defineStore(
  'userStore',
  () => {
    // 登录状态
    const isLogin = ref(false)
    // 用户信息
    const info = ref<Partial<SysUser>>({})
    // 访问令牌
    const accessToken = ref('')
    // 刷新令牌
    const refreshToken = ref('')
    // token过期时间戳(毫秒)
    const tokenExpireTime = ref(0)

    // 计算属性：获取用户信息
    const getUserInfo = computed(() => info.value)

    // 计算属性：是否为教师角色
    const isTeacher = computed(
      () => info.value.roles?.length === 1 && info.value.roles[0]?.name?.includes('教师'),
    )

    /**
     * 设置用户信息
     * @param newInfo 新的用户信息
     */
    const setUserInfo = (newInfo: SysUser) => {
      info.value = newInfo
    }

    /**
     * 设置登录状态
     * @param status 登录状态
     */
    const setLoginStatus = (status: boolean) => {
      isLogin.value = status
    }

    /**
     * 设置令牌
     * @param newAccessToken 访问令牌
     * @param newRefreshToken 刷新令牌（可选）
     * @param expireTime token过期时间戳（秒，可选）
     */
    const setToken = (newAccessToken: string, newRefreshToken?: string, expireTime?: number) => {
      accessToken.value = newAccessToken
      if (newRefreshToken) {
        refreshToken.value = newRefreshToken
      }
      if (expireTime) {
        // 转换为毫秒时间戳
        tokenExpireTime.value = expireTime * 1000
      }
    }

    /**
     * 检查token是否即将过期（过期前1小时）
     * @returns 是否即将过期
     */
    const isTokenNearExpiry = () => {
      if (!tokenExpireTime.value || !accessToken.value) {
        return false
      }

      const now = Date.now()
      const oneHourInMs = 60 * 60 * 1000 // 1小时的毫秒数

      // 如果当前时间 + 1小时 >= 过期时间，则认为即将过期
      return now + oneHourInMs >= tokenExpireTime.value
    }

    /**
     * 检查token是否已过期
     * @returns 是否已过期
     */
    const isTokenExpired = () => {
      if (!tokenExpireTime.value || !accessToken.value) {
        return false
      }

      return Date.now() >= tokenExpireTime.value
    }

    /**
     * 获取用户信息
     */
    const fetchUserProfile = async () => {
      try {
        const userData = await authProfileUsingGet({})
        if (userData) {
          setUserInfo(userData)
          return userData
        }
      }
      catch (error) {
        console.error('获取用户信息失败:', error)
        throw error
      }
    }

    /**
     * 退出登录
     * 清空所有用户相关状态
     */
    const logOut = () => {
      // 清空用户信息
      info.value = {}
      // 重置登录状态
      isLogin.value = false
      // 清空访问令牌
      accessToken.value = ''
      // 清空刷新令牌
      refreshToken.value = ''
      // 清空token过期时间
      tokenExpireTime.value = 0

      // 清空本地存储
      uni.removeStorageSync('userInfo')
      uni.removeStorageSync('token')

      toast.success('退出成功')
    }

    /**
     * 用户登录
     * @param credentials 登录参数
     */
    const login = async (credentials: LoginRequest) => {
      try {
        const loginData = await authLoginUsingPost({ body: credentials })

        if (loginData) {
          const { access_token, refresh_token, expire_time } = loginData

          // 设置令牌
          if (access_token) {
            setToken(access_token, refresh_token, expire_time)
            setLoginStatus(true)

            // 获取用户信息
            await fetchUserProfile()

            toast.success('登录成功')
            return loginData
          }
        }

        throw new Error('登录失败：未获取到有效令牌')
      }
      catch (error) {
        console.error('登录失败:', error)
        throw error
      }
    }

    /**
     * 刷新令牌
     */
    const refreshAuthToken = async () => {
      try {
        if (!refreshToken.value) {
          throw new Error('没有刷新令牌')
        }

        const refreshData = await authRefreshUsingPost({
          body: { refresh_token: refreshToken.value },
        })

        if (refreshData) {
          const { access_token, refresh_token: newRefreshToken, expire_time } = refreshData
          if (access_token) {
            setToken(access_token, newRefreshToken, expire_time)
            return access_token
          }
        }

        throw new Error('刷新令牌失败')
      }
      catch (error) {
        console.error('刷新令牌失败:', error)
        // 刷新失败，退出登录
        logOut()
        throw error
      }
    }

    return {
      isLogin,
      isTeacher,
      info,
      accessToken,
      refreshToken,
      tokenExpireTime,
      getUserInfo,
      setUserInfo,
      setLoginStatus,
      setToken,
      isTokenNearExpiry,
      isTokenExpired,
      login,
      fetchUserProfile,
      refreshAuthToken,
      logOut,
    }
  },
  {
    persist: true,
  },
)
