import { createContext, useContext, PropsWithChildren, useState } from 'react'
import Taro, { useLaunch } from '@tarojs/taro'
import { authClient } from '../api'
import { InferResponseType, InferRequestType } from 'hono'
import { useMutation } from '@tanstack/react-query'
import { isWeapp, isH5 } from './platform'

// 用户类型定义
export type User = InferResponseType<typeof authClient.me.$get, 200>
export type MiniLoginUser = InferResponseType<typeof authClient['mini-login']['$post'], 200>['user']
type LoginRequest = InferRequestType<typeof authClient.login.$post>['json']
type RegisterRequest = InferRequestType<typeof authClient.register.$post>['json']

interface AuthContextType {
  user: User | null
  login: (data: LoginRequest) => Promise<User>
  logout: () => Promise<void>
  register: (data: RegisterRequest) => Promise<User>
  updateUser: (userData: Partial<User>) => void
  isLoading: boolean
  isLoggedIn: boolean
}

const AuthContext = createContext<AuthContextType | undefined>(undefined)

export const AuthProvider: React.FC<PropsWithChildren> = ({ children }) => {

  // 用户状态
  const [user, setUser] = useState<User | null>(() => {
    // 从本地存储初始化用户信息
    const userInfoStr = Taro.getStorageSync('userInfo')
    if (userInfoStr) {
      try {
        return JSON.parse(userInfoStr)
      } catch {
        return null
      }
    }
    return null
  })

  // 获取用户信息的通用函数
  const fetchUserInfo = async (): Promise<User | null> => {
    // const token = Taro.getStorageSync('mini_token')
    // if (!token) {
    //   return null
    // }
    try {
      const response = await authClient.me.$get({})
      if (response.status !== 200) {
        throw new Error('获取用户信息失败')
      }
      const user = await response.json()
      Taro.setStorageSync('userInfo', JSON.stringify(user))
      return user
    } catch (error) {
      // Token失效时的处理逻辑
      console.debug('Token失效，开始处理重新登录逻辑')

      if (isWeapp()) {
        // 小程序环境：使用静默登录重新获取token
        console.debug('小程序环境，尝试静默登录')
        try {
          const loginRes = await Taro.login()
          if (loginRes.code) {
            const response = await authClient['mini-login'].$post({
              json: {
                code: loginRes.code,
                tenantId: Number(process.env.TARO_APP_TENANT_ID) || 1
              }
            })

            if (response.status === 200) {
              const { token: newToken } = await response.json()
              Taro.setStorageSync('mini_token', newToken)

              // 重新获取完整的用户信息
              const meResponse = await authClient.me.$get({})
              if (meResponse.status === 200) {
                const user = await meResponse.json()
                Taro.setStorageSync('userInfo', JSON.stringify(user))
                console.debug('静默登录成功，返回新用户信息')
                return user
              }
            }
          }
        } catch (silentLoginError) {
          console.debug('静默登录失败:', silentLoginError)
        }
      } else if (isH5()) {
        // H5环境：跳转到登录页
        console.debug('H5环境，跳转到登录页')
        Taro.redirectTo({ url: '/pages/login/index' })
      }

      // 如果重新登录失败或不是小程序环境，清除token并返回null
      Taro.removeStorageSync('mini_token')
      Taro.removeStorageSync('userInfo')
      return null
    }
  }

  // 静默登录mutation - 应用启动时自动尝试登录
  const silentLoginMutation = useMutation<User | null, Error, void>({
    mutationFn: async () => {
      // 使用统一的用户信息获取函数
      return await fetchUserInfo()
    },
    onSuccess: (user) => {
      if (user) {
        setUser(user)
      }
    }
  })

  

  // 在小程序启动时执行静默登录，刷新token和sessionKey
  useLaunch(() => {
    silentLoginMutation.mutate()
  })


  const loginMutation = useMutation<User, Error, LoginRequest>({
    mutationFn: async (data) => {
      const response = await authClient.login.$post({ json: data })
      if (response.status !== 200) {
        throw new Error('登录失败')
      }
      const { token, user } = await response.json()
      Taro.setStorageSync('mini_token', token)
      Taro.setStorageSync('userInfo', JSON.stringify(user))
      return user
    },
    onSuccess: (newUser) => {
      setUser(newUser)
    },
    onError: (error) => {
      Taro.showToast({
        title: error.message || '登录失败，请检查用户名和密码',
        icon: 'none',
        duration: 2000,
      })
    },
  })

  const registerMutation = useMutation<User, Error, RegisterRequest>({
    mutationFn: async (data) => {
      const response = await authClient.register.$post({ json: data })
      if (response.status !== 201) {
        throw new Error('注册失败')
      }
      const { token, user } = await response.json()
      Taro.setStorageSync('mini_token', token)
      Taro.setStorageSync('userInfo', JSON.stringify(user))
      return user
    },
    onSuccess: (newUser) => {
      setUser(newUser)
    },
    onError: (error) => {
      Taro.showToast({
        title: error.message || '注册失败，请重试',
        icon: 'none',
        duration: 2000,
      })
    },
  })

  const logoutMutation = useMutation<void, Error>({
    mutationFn: async () => {
      try {
        const response = await authClient.logout.$post({})
        if (response.status !== 200) {
          throw new Error('登出失败')
        }
      } catch (error) {
        console.error('Logout error:', error)
      } finally {
        Taro.removeStorageSync('mini_token')
        Taro.removeStorageSync('userInfo')
      }
    },
    onSuccess: () => {
      setUser(null)
      Taro.redirectTo({ url: '/pages/login/index' })
    },
    onError: (error) => {
      Taro.showToast({
        title: error.message || '登出失败',
        icon: 'none',
        duration: 2000,
      })
    },
  })

  const updateUserMutation = useMutation<User, Error, Partial<User>>({
    mutationFn: async (userData) => {
      const response = await authClient.me.$put({ json: userData })
      if (response.status !== 200) {
        throw new Error('更新用户信息失败')
      }
      const updatedUser = await response.json()
      Taro.setStorageSync('userInfo', JSON.stringify(updatedUser))
      return updatedUser
    },
    onSuccess: (updatedUser) => {
      setUser(updatedUser)
      Taro.showToast({
        title: '更新成功',
        icon: 'success',
        duration: 2000,
      })
    },
    onError: (error) => {
      Taro.showToast({
        title: error.message || '更新失败，请重试',
        icon: 'none',
        duration: 2000,
      })
    },
  })

  const updateUser = updateUserMutation.mutateAsync

  const value = {
    user: user || null,
    login: loginMutation.mutateAsync,
    logout: logoutMutation.mutateAsync,
    register: registerMutation.mutateAsync,
    updateUser,
    isLoading: loginMutation.isPending || registerMutation.isPending || logoutMutation.isPending || silentLoginMutation.isPending,
    isLoggedIn: !!user,
  }

  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>
}

export const useAuth = () => {
  const context = useContext(AuthContext)
  if (context === undefined) {
    throw new Error('useAuth must be used within an AuthProvider')
  }
  return context
}