import { createContext, useContext, PropsWithChildren } from 'react'
import Taro from '@tarojs/taro'
import { InferResponseType, InferRequestType } from 'hono'
import { QueryClient, useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { enterpriseAuthClient } from '../api'

// 用户类型定义 - 使用企业用户认证
export type User = InferResponseType<typeof enterpriseAuthClient.me.$get, 200>
type LoginRequest = InferRequestType<typeof enterpriseAuthClient.login.$post>['json']
// 企业用户注册可能由管理员创建，前端不提供注册接口
type RegisterRequest = { username: string; password: string }

export 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)

// 导出queryClient以供外部使用（如果需要）
export const queryClient = new QueryClient()

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

  const { data: user, isLoading } = useQuery<User | null, Error>({
    queryKey: ['currentUser'],
    queryFn: async () => {
      const token = Taro.getStorageSync('enterprise_token')
      if (!token) {
        return null
      }
      try {
        const response = await enterpriseAuthClient.me.$get({})
        if (response.status !== 200) {
          throw new Error('获取用户信息失败')
        }
        const user = await response.json()
        Taro.setStorageSync('enterpriseUserInfo', JSON.stringify(user))
        return user
      } catch (error) {
        Taro.removeStorageSync('enterprise_token')
        Taro.removeStorageSync('enterpriseUserInfo')
        return null
      }
    },
    staleTime: Infinity, // 用户信息不常变动，设为无限期
    refetchOnWindowFocus: false, // 失去焦点不重新获取
    refetchOnReconnect: false, // 网络重连不重新获取
  })

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

  const registerMutation = useMutation<User, Error, RegisterRequest>({
    mutationFn: async () => {
      // 企业用户注册由管理员创建，前端不提供注册接口
      throw new Error('企业用户注册请联系管理员创建账户')
    },
    onSuccess: (newUser) => {
      queryClient.setQueryData(['currentUser'], newUser)
    },
    onError: (error) => {
      Taro.showToast({
        title: error.message || '企业用户注册请联系管理员',
        icon: 'none',
        duration: 3000,
      })
    },
  })

  const logoutMutation = useMutation<void, Error>({
    mutationFn: async () => {
      try {
        const response = await enterpriseAuthClient.logout.$post({})
        if (response.status !== 200) {
          throw new Error('登出失败')
        }
      } catch (error) {
        console.error('Logout error:', error)
      } finally {
        Taro.removeStorageSync('enterprise_token')
        Taro.removeStorageSync('enterprise_refresh_token')
        Taro.removeStorageSync('enterpriseUserInfo')
      }
    },
    onSuccess: () => {
      queryClient.setQueryData(['currentUser'], 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 () => {
      // 企业用户信息更新可能由管理员管理，前端不提供更新接口
      throw new Error('企业用户信息更新请联系管理员')
    },
    onSuccess: (updatedUser) => {
      queryClient.setQueryData(['currentUser'], 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: isLoading || loginMutation.isPending || registerMutation.isPending || logoutMutation.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
}