/**
 * AuthProvider - 全局会话上下文
 * 
 * 提供：
 * - 会话状态（user, roles, isAdmin）
 * - 登录/登出方法
 * - 会话恢复（启动时自动刷新）
 */

import {
  useEffect,
  useState,
  useCallback,
  type ReactNode,
} from 'react'
import { useNavigate } from 'react-router-dom'
import type { SessionUser, Role, TokenBundle } from '@/types'
import { get } from '@/lib/http'
import {
  setRefreshToken,
  clearRefreshToken,
  hasSessionPresenceCookie,
} from '@/lib/storage'
import {
  setAccessToken,
  getCurrentUser,
  setCurrentUser,
  getCurrentRoles,
  setCurrentRoles,
  clearSession,
  isAuthenticated,
  isAccessTokenExpired,
} from '@/lib/http/auth-session'
import { initCSRFToken, clearCSRFToken } from '@/lib/http/csrf'
import { logout as logoutRequest, refreshSession } from '@/services/auth'
import { AuthContext, type AuthContextValue } from './auth-context'

// ==================== Provider ====================

interface AuthProviderProps {
  children: ReactNode
}

export function AuthProvider({ children }: AuthProviderProps) {
  const [user, setUser] = useState<SessionUser | null>(getCurrentUser())
  const [roles, setRoles] = useState<Role[]>(getCurrentRoles())
  const [isLoading, setIsLoading] = useState(true)
  const navigate = useNavigate()
  const effectiveUser = user ?? getCurrentUser()
  const effectiveRoles = roles.length > 0 ? roles : getCurrentRoles()

  // 判断是否为管理员
  const isAdmin = effectiveRoles.some((role) => role.code === 'admin')

  /**
   * 获取用户角色
   */
  const fetchUserRoles = useCallback(async (userId: number): Promise<Role[]> => {
    try {
      const result = await get<Role[]>(`/users/${userId}/roles`)
      return result
    } catch {
      return []
    }
  }, [])

  /**
   * 登录成功回调
   */
  const onLoginSuccess = useCallback(async (tokenBundle: TokenBundle) => {
    // 保存 tokens
    setAccessToken(tokenBundle.access_token, tokenBundle.expires_in)
    setRefreshToken(tokenBundle.refresh_token)
    
    // 保存用户信息
    setCurrentUser(tokenBundle.user)
    setUser(tokenBundle.user)
    
    // 获取角色
    const userRoles = await fetchUserRoles(tokenBundle.user.id)
    setCurrentRoles(userRoles)
    setRoles(userRoles)
    
    // 初始化 CSRF Token
    await initCSRFToken()
  }, [fetchUserRoles])

  /**
   * 刷新用户信息
   */
  const refreshUser = useCallback(async () => {
    try {
      const userInfo = await get<SessionUser>('/auth/userinfo')
      setCurrentUser(userInfo)
      setUser(userInfo)
      
      const userRoles = await fetchUserRoles(userInfo.id)
      setCurrentRoles(userRoles)
      setRoles(userRoles)
    } catch {
      // 刷新失败，清除会话
      setUser(null)
      setRoles([])
    }
  }, [fetchUserRoles])

  /**
   * 登出
   */
  const logout = useCallback(async () => {
    try {
      await logoutRequest()
    } catch {
      // 忽略登出请求错误
    } finally {
      // 无论请求成功与否，都清除本地会话和 CSRF Token
      clearRefreshToken()
      clearSession()
      clearCSRFToken()
      setUser(null)
      setRoles([])
      navigate('/login')
    }
  }, [navigate])

  /**
   * 会话恢复（应用启动时，只运行一次）
   */
  useEffect(() => {
    const restoreSession = async () => {
      // 如果已有 access_token 且未过期，直接使用
      if (isAuthenticated() && !isAccessTokenExpired()) {
        const currentUser = getCurrentUser()
        const currentRoles = getCurrentRoles()
        
        if (currentUser) {
          setUser(currentUser)
          setRoles(currentRoles)
          await initCSRFToken()
          setIsLoading(false)
          return
        }
      }

      if (!hasSessionPresenceCookie()) {
        clearRefreshToken()
        clearSession()
        setUser(null)
        setRoles([])
        setIsLoading(false)
        return
      }

      try {
        const result = await refreshSession()

        // 保存 tokens
        setAccessToken(result.access_token, result.expires_in)
        setRefreshToken(result.refresh_token)

        // 保存用户信息
        setCurrentUser(result.user)
        setUser(result.user)

        // 获取角色
        const userRoles = await fetchUserRoles(result.user.id)
        setCurrentRoles(userRoles)
        setRoles(userRoles)
        await initCSRFToken()
      } catch {
        // 刷新失败，清除会话
        clearRefreshToken()
        clearSession()
        setUser(null)
        setRoles([])
      }

      setIsLoading(false)
    }

    restoreSession()
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []) // 只在挂载时运行一次，不依赖 location.pathname

  const value: AuthContextValue = {
    user: effectiveUser,
    roles: effectiveRoles,
    isAdmin,
    isAuthenticated: effectiveUser !== null && isAuthenticated(),
    isLoading,
    onLoginSuccess,
    logout,
    refreshUser,
  }

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