import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react'
import Taro from '@tarojs/taro'
import { QueryClient, useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { talentAuthClient } from '../api'
import type { InferResponseType } from 'hono'

// 使用RPC类型推断，确保类型与后端API完全一致
export type TalentUserInfo = InferResponseType<typeof talentAuthClient.me.$get, 200>

export interface AuthContextType {
  isLoggedIn: boolean
  user: TalentUserInfo | null
  token: string | null
  login: (identifier: string, password: string) => Promise<void>
  logout: () => Promise<void>
  refreshUser: () => Promise<void>
  loading: boolean
}

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

const TOKEN_KEY = 'talent_token'
const USER_KEY = 'talent_user'

// 导出queryClient以供外部使用（与mini-enterprise-auth-ui保持一致）
export const queryClient = new QueryClient()

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

  const [_isLoggedIn, setIsLoggedIn] = useState(false)
  const [token, setToken] = useState<string | null>(null)
  const [loading, setLoading] = useState(true)

  // 使用React Query管理用户状态
  const { data: user, isLoading } = useQuery<TalentUserInfo | null, Error>({
    queryKey: ['talentCurrentUser'],
    queryFn: async () => {
      const storedToken = Taro.getStorageSync(TOKEN_KEY)
      if (!storedToken) {
        return null
      }

      try {
        const response = await talentAuthClient.me.$get()
        if (response.status !== 200) {
          throw new Error('获取用户信息失败')
        }

        // 使用 response.json() 解析数据
        const userInfo = await response.json()

        // 缓存到本地存储（序列化为JSON字符串）
        Taro.setStorageSync(USER_KEY, JSON.stringify(userInfo))
        return userInfo
      } catch (error) {
        console.error('获取用户信息失败:', error)
        Taro.removeStorageSync(TOKEN_KEY)
        Taro.removeStorageSync(USER_KEY)
        return null
      }
    },
    staleTime: Infinity,
    refetchOnWindowFocus: false,
    refetchOnReconnect: false,
  })

  // 同步isLoggedIn状态
  useEffect(() => {
    setIsLoggedIn(!!user)
    setToken(Taro.getStorageSync(TOKEN_KEY) || null)
    setLoading(false)
  }, [user])

  const loginMutation = useMutation<void, Error, { identifier: string; password: string }>({
    mutationFn: async ({ identifier, password }) => {
      const response = await talentAuthClient.login.$post({
        json: {
          identifier: identifier.trim(),
          password: password.trim()
        }
      })

      if (response.status !== 200) {
        throw new Error('登录失败')
      }

      // 使用 response.json() 解析数据
      const data = await response.json()
      const { token, user } = data

      // 保存到本地存储（user序列化为JSON字符串）
      Taro.setStorageSync(TOKEN_KEY, token)
      Taro.setStorageSync(USER_KEY, JSON.stringify(user))

      setToken(token)
    },
    onSuccess: () => {
      // 刷新用户信息
      queryClient.invalidateQueries({ queryKey: ['talentCurrentUser'] })
    },
    onError: (error) => {
      Taro.showToast({
        title: error.message || '登录失败，请检查账号和密码',
        icon: 'none',
        duration: 2000,
      })
    },
  })

  const logoutMutation = useMutation<void, Error>({
    mutationFn: async () => {
      try {
        // TODO: 调用退出API
        // await talentAuthClient.logout.$post()
      } catch (error) {
        console.error('Logout error:', error)
      } finally {
        Taro.removeStorageSync(TOKEN_KEY)
        Taro.removeStorageSync(USER_KEY)
      }
    },
    onSuccess: () => {
      // 先清除用户状态
      queryClient.setQueryData(['talentCurrentUser'], null)
      // 立即跳转到登录页（不使用异步，因为 reLaunch 不返回 Promise）
      Taro.reLaunch({ url: '/pages/login/index' })
    },
    onError: (error) => {
      Taro.showToast({
        title: error.message || '登出失败',
        icon: 'none',
        duration: 2000,
      })
    },
  })

  const login = async (identifier: string, password: string): Promise<void> => {
    await loginMutation.mutateAsync({ identifier, password })
  }

  const logout = async (): Promise<void> => {
    await logoutMutation.mutateAsync()
  }

  const refreshUser = async (): Promise<void> => {
    await queryClient.invalidateQueries({ queryKey: ['talentCurrentUser'] })
  }

  const value: AuthContextType = {
    isLoggedIn: !!user,
    user: user || null,
    token,
    login,
    logout,
    refreshUser,
    loading: loading || isLoading,
  }

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

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

/**
 * useRequireAuth Hook
 * 检查登录状态，未登录则重定向到登录页
 *
 * 参考实现: mini-enterprise-auth-ui/src/hooks/useRequireAuth.ts
 */
export const useRequireAuth = (): void => {
  const { isLoggedIn, loading } = useAuth()

  useEffect(() => {
    // 只有在非loading状态且未登录时才跳转
    if (!loading && !isLoggedIn) {
      // 使用 reLaunch 而不是 redirectTo，确保在 TabBar 页面也能正常跳转
      Taro.reLaunch({
        url: '/pages/login/index'
      })
    }
  }, [isLoggedIn, loading])
}

export default AuthContext
