import { useMutation } from '@apollo/client' import { useState, useEffect } from 'react' import { SEND_SMS_CODE, VERIFY_SMS_CODE, REGISTER_FULFILLMENT_ORGANIZATION, REGISTER_SELLER_ORGANIZATION } from '@/graphql/mutations' import { GET_ME } from '@/graphql/queries' import { setAuthToken, setUserData, removeAuthToken, getAuthToken, apolloClient } from '@/lib/apollo-client' import { useApolloRefresh } from './useApolloRefresh' interface User { id: string phone: string avatar?: string managerName?: string createdAt?: string organization?: { id: string inn: string kpp?: string name?: string fullName?: string address?: string addressFull?: string ogrn?: string ogrnDate?: string status?: string actualityDate?: string registrationDate?: string liquidationDate?: string managementName?: string managementPost?: string opfCode?: string opfFull?: string opfShort?: string okato?: string oktmo?: string okpo?: string okved?: string employeeCount?: number revenue?: string taxSystem?: string phones?: unknown emails?: unknown type: 'FULFILLMENT' | 'SELLER' | 'LOGIST' | 'WHOLESALE' apiKeys: Array<{ id: string marketplace: 'WILDBERRIES' | 'OZON' isActive: boolean validationData?: unknown }> } } interface UseAuthReturn { // SMS методы sendSmsCode: (phone: string) => Promise<{ success: boolean; message: string }> verifySmsCode: (phone: string, code: string) => Promise<{ success: boolean message: string user?: User }> // Регистрация организаций registerFulfillmentOrganization: (phone: string, inn: string) => Promise<{ success: boolean message: string user?: User }> registerSellerOrganization: (data: { phone: string wbApiKey?: string ozonApiKey?: string ozonClientId?: string }) => Promise<{ success: boolean message: string user?: User }> // Состояние user: User | null isAuthenticated: boolean isLoading: boolean checkAuth: () => Promise logout: () => void } export const useAuth = (): UseAuthReturn => { // Инициализируем состояния с проверкой токена const [isLoading, setIsLoading] = useState(false) const [user, setUser] = useState(null) const [isAuthenticated, setIsAuthenticated] = useState(() => { // Проверяем наличие токена при инициализации return !!getAuthToken() }) const [isCheckingAuth, setIsCheckingAuth] = useState(false) // Защита от повторных вызовов const { refreshApolloClient } = useApolloRefresh() const [sendSmsCodeMutation] = useMutation(SEND_SMS_CODE) const [verifySmsCodeMutation] = useMutation(VERIFY_SMS_CODE) const [registerFulfillmentMutation] = useMutation(REGISTER_FULFILLMENT_ORGANIZATION) const [registerSellerMutation] = useMutation(REGISTER_SELLER_ORGANIZATION) // Проверка авторизации при инициализации const checkAuth = async () => { if (isCheckingAuth) { console.log('useAuth - checkAuth already in progress, skipping') return } const token = getAuthToken() console.log('useAuth - checkAuth called, token exists:', !!token) if (!token) { setIsAuthenticated(false) setUser(null) setIsCheckingAuth(false) return } setIsCheckingAuth(true) try { console.log('useAuth - Making GET_ME query') const { data } = await apolloClient.query({ query: GET_ME, errorPolicy: 'all', fetchPolicy: 'network-only' // Всегда делаем свежий запрос }) console.log('useAuth - GET_ME response:', !!data?.me) if (data?.me) { setUser(data.me) setIsAuthenticated(true) setUserData(data.me) console.log('useAuth - User authenticated:', data.me.phone) } else { setIsAuthenticated(false) setUser(null) } } catch (error: unknown) { console.log('useAuth - GET_ME error:', error) if ((error as { graphQLErrors?: Array<{ extensions?: { code?: string } }> })?.graphQLErrors?.some((e) => e.extensions?.code === 'UNAUTHENTICATED')) { logout() } else { setIsAuthenticated(false) setUser(null) } } finally { setIsCheckingAuth(false) } } // Проверяем авторизацию при загрузке компонента только если нет данных пользователя useEffect(() => { const token = getAuthToken() console.log('useAuth - useEffect init, token exists:', !!token, 'user exists:', !!user, 'isChecking:', isCheckingAuth) if (token && !user && !isCheckingAuth) { console.log('useAuth - Running checkAuth because token exists but no user data') checkAuth() } else if (!token) { console.log('useAuth - No token, setting unauthenticated state') setIsAuthenticated(false) setUser(null) } }, []) // eslint-disable-line react-hooks/exhaustive-deps const sendSmsCode = async (phone: string) => { try { setIsLoading(true) const { data } = await sendSmsCodeMutation({ variables: { phone } }) return { success: data.sendSmsCode.success, message: data.sendSmsCode.message } } catch (error) { console.error('Error sending SMS code:', error) return { success: false, message: 'Ошибка при отправке SMS кода' } } finally { setIsLoading(false) } } const verifySmsCode = async (phone: string, code: string) => { try { setIsLoading(true) console.log('useAuth - Starting verifySmsCode mutation with:', { phone, code }) const { data } = await verifySmsCodeMutation({ variables: { phone, code } }) console.log('useAuth - GraphQL response data:', data) const result = data.verifySmsCode console.log('useAuth - SMS verification result:', { success: result.success, hasToken: !!result.token, hasUser: !!result.user, message: result.message }) if (result.success && result.token && result.user) { // Сохраняем токен и данные пользователя console.log('useAuth - Saving token:', result.token ? `${result.token.substring(0, 20)}...` : 'No token') setAuthToken(result.token) setUserData(result.user) // Обновляем состояние хука setUser(result.user) setIsAuthenticated(true) console.log('useAuth - State updated: user set, isAuthenticated=true') // Проверяем что токен действительно сохранился const savedToken = typeof window !== 'undefined' ? localStorage.getItem('authToken') : null console.log('useAuth - Token saved to localStorage:', savedToken ? `${savedToken.substring(0, 20)}...` : 'Not saved') // Принудительно обновляем Apollo Client refreshApolloClient() return { success: true, message: result.message, user: result.user } } return { success: false, message: result.message } } catch (error) { console.error('Error verifying SMS code:', error) console.error('Error details:', { message: error instanceof Error ? error.message : 'Unknown error', graphQLErrors: (error as { graphQLErrors?: unknown })?.graphQLErrors, networkError: (error as { networkError?: unknown })?.networkError }) return { success: false, message: 'Ошибка при проверке SMS кода' } } finally { setIsLoading(false) } } const registerFulfillmentOrganization = async (phone: string, inn: string) => { try { setIsLoading(true) // Проверяем токен перед запросом const currentToken = typeof window !== 'undefined' ? localStorage.getItem('authToken') : null console.log('useAuth - Token before registerFulfillment request:', currentToken ? `${currentToken.substring(0, 20)}...` : 'No token') const { data } = await registerFulfillmentMutation({ variables: { input: { phone, inn } } }) const result = data.registerFulfillmentOrganization if (result.success && result.user) { // Обновляем данные пользователя setUserData(result.user) return { success: true, message: result.message, user: result.user } } return { success: false, message: result.message } } catch (error) { console.error('Error registering fulfillment organization:', error) return { success: false, message: 'Ошибка при регистрации фулфилмент организации' } } finally { setIsLoading(false) } } const registerSellerOrganization = async (data: { phone: string wbApiKey?: string ozonApiKey?: string ozonClientId?: string }) => { try { setIsLoading(true) const { data: result } = await registerSellerMutation({ variables: { input: data } }) const registerResult = result.registerSellerOrganization if (registerResult.success && registerResult.user) { // Обновляем данные пользователя setUserData(registerResult.user) return { success: true, message: registerResult.message, user: registerResult.user } } return { success: false, message: registerResult.message } } catch (error) { console.error('Error registering seller organization:', error) return { success: false, message: 'Ошибка при регистрации селлер организации' } } finally { setIsLoading(false) } } const logout = () => { console.log('useAuth - Logging out') removeAuthToken() setUser(null) setIsAuthenticated(false) refreshApolloClient() // Перенаправляем на главную страницу if (typeof window !== 'undefined') { window.location.href = '/' } } return { // SMS методы sendSmsCode, verifySmsCode, // Регистрация организаций registerFulfillmentOrganization, registerSellerOrganization, // Состояние user, isAuthenticated, isLoading, checkAuth, logout } }