import React, { createContext, useContext, useState, useEffect, type ReactNode } from 'react'
import Taro from '@tarojs/taro'
import type { User } from '@/api/system/user/model'
import { getUserInfo } from '@/api/layout'
import { saveStorageByLoginUser, clearStorageByLoginUser } from '@/utils/server'
import { isUserDisabled, blockDisabledUser } from '@/utils/auth'

interface UserContextType {
  user: User | null
  isLoggedIn: boolean
  loading: boolean
  loginUser: (token: string, userInfo: User) => void
  logoutUser: () => void
  refreshUser: () => Promise<User | null>
  syncFromStorage: () => boolean
}

const UserContext = createContext<UserContextType | undefined>(undefined)

export const UserProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
  const [user, setUser] = useState<User | null>(null)
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    const init = async () => {
      const token = Taro.getStorageSync('access_token')
      const userData = Taro.getStorageSync('User')

      // 情况1: 有本地token和用户数据，先用缓存快速显示，再异步校验状态
      if (token && userData) {
        const parsed = typeof userData === 'string' ? JSON.parse(userData) : userData
        setUser(parsed as User)
        setLoading(false)

        // 异步从服务端校验用户是否被禁用（防止被禁用后仍可使用）
        verifyUserStatusFromServer()
        return
      }

      // 情况2: 有token但没有用户数据，尝试从接口获取
      if (token) {
        try {
          const userInfo = await getUserInfo()
          if (isUserDisabled(userInfo)) {
            blockDisabledUser(userInfo)
            setUser(null)
            setLoading(false)
            return
          }
          setUser(userInfo)
          setLoading(false)
          return
        } catch {
          // token无效，清除
          clearStorageByLoginUser()
        }
      }

      // 无本地token，保持未登录状态
      setLoading(false)
    }
    init()
  }, [])

  /** 异步从服务端拉取最新用户信息，校验是否被禁用 */
  const verifyUserStatusFromServer = async () => {
    try {
      const userInfo = await getUserInfo()
      if (isUserDisabled(userInfo)) {
        // 用户已被禁用，拦截
        blockDisabledUser(userInfo)
        setUser(null)
      } else {
        // 状态正常，更新本地缓存和状态
        const token = Taro.getStorageSync('access_token')
        if (token) {
          saveStorageByLoginUser(token, userInfo)
        }
        setUser(userInfo)
      }
    } catch {
      // 网络错误或token失效，静默处理（已有缓存的登录态可用）
    }
  }

  const loginUser = (token: string, userInfo: User) => {
    if (isUserDisabled(userInfo)) {
      blockDisabledUser(userInfo)
      return
    }
    saveStorageByLoginUser(token, userInfo)
    setUser(userInfo)
  }

  const logoutUser = () => {
    clearStorageByLoginUser()
    setUser(null)
  }

  /** 从 storage 快速同步用户状态（无需网络请求），供页面 useDidShow 调用 */
  const syncFromStorage = (): boolean => {
    const token = Taro.getStorageSync('access_token')
    const userData = Taro.getStorageSync('User')
    if (token && userData) {
      const parsed = typeof userData === 'string' ? JSON.parse(userData) : userData
      // 快速检查缓存中的 status，如果已禁用则拦截
      if (isUserDisabled(parsed)) {
        blockDisabledUser(parsed)
        setUser(null)
        return false
      }
      setUser(parsed as User)
      return true
    }
    if (!token) {
      setUser(null)
    }
    return false
  }

  const refreshUser = async (): Promise<User | null> => {
    if (!Taro.getStorageSync('access_token')) return null
    try {
      const userInfo = await getUserInfo()
      if (isUserDisabled(userInfo)) {
        blockDisabledUser(userInfo)
        setUser(null)
        return null
      }
      const token = Taro.getStorageSync('access_token')
      if (token) {
        saveStorageByLoginUser(token, userInfo)
      }
      setUser(userInfo)
      return userInfo
    } catch {
      return null
    }
  }

  return (
    <UserContext.Provider
      value={{ user, isLoggedIn: !!user, loading, loginUser, logoutUser, refreshUser, syncFromStorage }}
    >
      {children}
    </UserContext.Provider>
  )
}

export const useUserContext = (): UserContextType => {
  const context = useContext(UserContext)
  if (!context) {
    throw new Error('useUserContext must be used within UserProvider')
  }
  return context
}
