import React, { createContext, useCallback, useContext, useEffect, useState } from 'react'
import { XuqmSDK, ImSDK } from '@xuqm/rn-sdk'
import { demoApi, type UserProfile } from '../api/demo'
import { save, load, clearSession, K } from '../utils/storage'

const APP_ID = 'ak_demo_chat'
const SERVER_URL = 'https://sentry.xuqinmin.com'

interface AuthState {
  ready: boolean
  userId: string | null
  profile: UserProfile | null
}

interface AuthContextValue extends AuthState {
  login(userId: string, password: string): Promise<void>
  register(userId: string, password: string, nickname: string): Promise<void>
  logout(): Promise<void>
  refreshProfile(): Promise<void>
  updateProfile(data: Partial<Pick<UserProfile, 'nickname' | 'avatar' | 'gender'>>): Promise<void>
}

const AuthContext = createContext<AuthContextValue | null>(null)

export function AuthProvider({ children }: { children: React.ReactNode }) {
  const [state, setState] = useState<AuthState>({ ready: false, userId: null, profile: null })

  const initSDK = useCallback(async (userId: string, imToken: string, profile: UserProfile) => {
    await XuqmSDK.initialize({ appId: APP_ID, serverUrl: SERVER_URL })
    await ImSDK.loginWithToken(userId, imToken, 'xuqm_im')
    setState({ ready: true, userId, profile })
  }, [])

  useEffect(() => {
    const restore = async () => {
      try {
        const demoToken = await load<string>(K.DEMO_TOKEN)
        const imToken = await load<string>(K.IM_TOKEN)
        const profile = await load<UserProfile>(K.PROFILE)
        if (demoToken && imToken && profile) {
          await initSDK(profile.userId, imToken, profile)
          return
        }
      } catch {
        await clearSession()
      }
      setState(s => ({ ...s, ready: true }))
    }
    restore()
  }, [initSDK])

  const handleAuthResult = useCallback(async (result: { demoToken: string; imToken: string; profile: UserProfile }) => {
    await save(K.DEMO_TOKEN, result.demoToken)
    await save(K.IM_TOKEN, result.imToken)
    await save(K.PROFILE, result.profile)
    await initSDK(result.profile.userId, result.imToken, result.profile)
  }, [initSDK])

  const login = useCallback(async (userId: string, password: string) => {
    const result = await demoApi.login(userId, password)
    await handleAuthResult(result)
  }, [handleAuthResult])

  const register = useCallback(async (userId: string, password: string, nickname: string) => {
    const result = await demoApi.register(userId, password, nickname)
    await handleAuthResult(result)
  }, [handleAuthResult])

  const logout = useCallback(async () => {
    ImSDK.disconnect()
    await clearSession()
    setState({ ready: true, userId: null, profile: null })
  }, [])

  const refreshProfile = useCallback(async () => {
    const profile = await demoApi.getProfile()
    await save(K.PROFILE, profile)
    setState(s => ({ ...s, profile }))
  }, [])

  const updateProfile = useCallback(async (data: Partial<Pick<UserProfile, 'nickname' | 'avatar' | 'gender'>>) => {
    const profile = await demoApi.updateProfile(data)
    await save(K.PROFILE, profile)
    setState(s => ({ ...s, profile }))
  }, [])

  return (
    <AuthContext.Provider value={{ ...state, login, register, logout, refreshProfile, updateProfile }}>
      {children}
    </AuthContext.Provider>
  )
}

export function useAuth(): AuthContextValue {
  const ctx = useContext(AuthContext)
  if (!ctx) throw new Error('useAuth must be used inside AuthProvider')
  return ctx
}
