'use client'

import { createContext, useContext, useState, useCallback, useEffect, type ReactNode } from 'react'
import type { User } from '@/types'
import { api, setAccessToken } from '@/lib/api'

/**
 * Состояние аутентификации, доступное через контекст
 * @property user - Текущий пользователь или null
 * @property isLoading - Флаг загрузки сессии
 * @property login - Функция входа (email, пароль)
 * @property register - Функция регистрации (email, пароль, роль)
 * @property logout - Функция выхода
 * @property refreshSession - Функция обновления сессии
 */
interface AuthState {
  user: User | null
  isLoading: boolean
  login: (email: string, password: string) => Promise<void>
  register: (email: string, password: string, role: string) => Promise<void>
  logout: () => Promise<void>
  refreshSession: () => Promise<void>
}

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

/**
 * Провайдер аутентификации. Оборачивает приложение в контекст AuthState.
 * При монтировании пытается восстановить сессию через /auth/me.
 * Предоставляет дочерним компонентам методы login, register, logout, refreshSession.
 */
export function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<User | null>(null)
  const [isLoading, setIsLoading] = useState(true)

  const refreshSession = useCallback(async () => {
    try {
      const res = await api.get<User>('/auth/me')
      setUser(res)
    } catch {
      setAccessToken(null)
      setUser(null)
    }
  }, [])

  useEffect(() => {
    refreshSession().finally(() => setIsLoading(false))
  }, [refreshSession])

  const login = useCallback(async (email: string, password: string) => {
    const res = await api.post<{ user: User; access_token: string }>('/auth/login', { email, password })
    setAccessToken(res.access_token)
    setUser(res.user)
  }, [])

  const register = useCallback(async (email: string, password: string, role: string) => {
    const res = await api.post<{ user: User; access_token: string }>('/auth/register', { email, password, role })
    setAccessToken(res.access_token)
    setUser(res.user)
  }, [])

  const logout = useCallback(async () => {
    try {
      await api.post('/auth/logout', {})
    } catch {}
    setAccessToken(null)
    setUser(null)
  }, [])

  return (
    <AuthContext.Provider value={{ user, isLoading, login, register, logout, refreshSession }}>
      {children}
    </AuthContext.Provider>
  )
}

/**
 * Хук для доступа к контексту аутентификации.
 * Должен использоваться внутри компонента AuthProvider.
 * @returns Объект AuthState с пользователем, состоянием загрузки и методами auth
 * @throws Ошибка, если хук вызван вне AuthProvider
 */
export function useAuth() {
  const ctx = useContext(AuthContext)
  if (!ctx) throw new Error('useAuth must be used within AuthProvider')
  return ctx
}