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, loginByOpenId } from '@/api/layout'
import { saveStorageByLoginUser, clearStorageByLoginUser } from '@/utils/server'
import { TenantId } from '@/config/app'

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)
        return
      }

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

      // 情况3: 没有本地token，尝试静默登录（老用户自动登录）
      try {
        const loginResult = await new Promise<{ access_token?: string; user?: User }>((resolve, reject) => {
          Taro.login({
            success: (res) => {
              if (res.code) {
                loginByOpenId({ code: res.code, tenantId: TenantId })
                  .then(resolve)
                  .catch(reject)
              } else {
                reject(new Error('no code'))
              }
            },
            fail: reject,
          })
        })
        // 静默登录成功（老用户），自动完成登录
        if (loginResult?.access_token && loginResult?.user) {
          saveStorageByLoginUser(loginResult.access_token, loginResult.user)
          setUser(loginResult.user)
        }
      } catch {
        // 静默登录失败（非老用户或网络问题），保持未登录状态
      }

      setLoading(false)
    }
    init()
  }, [])

  const loginUser = (token: string, userInfo: User) => {
    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
      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()
      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
}
