import { Component, createContext, createSignal, JSX, onMount, useContext } from 'solid-js'
import { AuthSuccess } from '~/graphql/generated/graphql'
import { query } from '../graphql'
import { ADMIN_LOGIN_MUTATION, ADMIN_LOGOUT_MUTATION } from '../graphql/mutations'
import {
  AUTH_TOKEN_KEY,
  CSRF_TOKEN_KEY,
  checkAuthStatus,
  clearAuthTokens,
  getAuthTokenFromCookie,
  getCsrfTokenFromCookie,
  saveAuthToken
} from '../utils/auth'
/**
 * Модуль авторизации
 * @module auth
 */

/**
 * Интерфейс для учетных данных
 */
export interface Credentials {
  email: string
  password: string
}

/**
 * Интерфейс для результата авторизации
 */
export interface LoginResult {
  success: boolean
  token?: string
  error?: string
}

// Экспортируем утилитарные функции для обратной совместимости
export {
  AUTH_TOKEN_KEY,
  CSRF_TOKEN_KEY,
  getAuthTokenFromCookie,
  getCsrfTokenFromCookie,
  checkAuthStatus,
  clearAuthTokens,
  saveAuthToken
}

interface AuthContextType {
  isAuthenticated: () => boolean
  isReady: () => boolean
  login: (username: string, password: string) => Promise<void>
  logout: () => Promise<void>
}

const AuthContext = createContext<AuthContextType>({
  isAuthenticated: () => false,
  isReady: () => false,
  login: async () => {},
  logout: async () => {}
})

export const useAuth = () => useContext(AuthContext)

interface AuthProviderProps {
  children: JSX.Element
}

export const AuthProvider: Component<AuthProviderProps> = (props) => {
  console.log('[AuthProvider] Initializing...')
  // Начинаем с false чтобы избежать мерцания, реальная проверка будет в onMount
  const [isAuthenticated, setIsAuthenticated] = createSignal(false)
  const [isReady, setIsReady] = createSignal(false)
  
  // Флаг для предотвращения повторных инициализаций
  let isInitializing = false

  console.log('[AuthProvider] Initial auth state: not authenticated (will check via GraphQL)')

  // Инициализация авторизации при монтировании
  onMount(async () => {
    // Защита от повторных вызовов
    if (isInitializing) {
      console.log('[AuthProvider] Already initializing, skipping...')
      return
    }
    
    isInitializing = true
    console.log('[AuthProvider] Performing auth initialization...')

    // 🍪 Для httpOnly cookies проверяем авторизацию через GraphQL запрос
    try {
      console.log('[AuthProvider] Checking authentication via GraphQL...')

      // Добавляем таймаут для запроса (5 секунд для лучшего UX)
      const timeoutPromise = new Promise((_, reject) => 
        setTimeout(() => reject(new Error('Auth check timeout')), 5000)
      )

      const authPromise = query<{ me: { id: string } | null }>(
        `${location.origin}/graphql`,
        `
        query CheckAuth {
          me {
            id
            name
            email
          }
        }
      `
      )

      // Делаем тестовый запрос для проверки авторизации с таймаутом
      const result = (await Promise.race([authPromise, timeoutPromise])) as {
        me: { id: string; name: string; email: string } | null
      }

      if (result?.me?.id) {
        console.log('[AuthProvider] User authenticated via httpOnly cookie:', result.me.id)
        setIsAuthenticated(true)
      } else {
        console.log('[AuthProvider] No authenticated user found')
        setIsAuthenticated(false)
      }
    } catch (error) {
      console.log('[AuthProvider] Authentication check failed:', error)
      setIsAuthenticated(false)
    } finally {
      // Всегда устанавливаем ready в true, даже при ошибке
      console.log('[AuthProvider] Auth initialization complete, ready for requests')
      setIsReady(true)
      isInitializing = false
    }
  })

  const login = async (username: string, password: string) => {
    console.log('[AuthProvider] Attempting login...')
    try {
      const result = await query<{
        login: { success: boolean; token?: string }
      }>(`${location.origin}/graphql`, ADMIN_LOGIN_MUTATION, {
        email: username,
        password
      })

      if (result?.login?.success) {
        console.log('[AuthProvider] Login successful')
        // Backend автоматически установил session_token cookie при успешном login
        console.log('[AuthProvider] Token saved in httpOnly cookie by backend')
        setIsAuthenticated(true)
        // Убираем window.location.href - пусть роутер сам обрабатывает навигацию
      } else {
        console.error('[AuthProvider] Login failed')
        throw new Error('Неверные учетные данные')
      }
    } catch (error) {
      console.error('[AuthProvider] Login error:', error)
      throw error
    }
  }

  const logout = async () => {
    console.log('[AuthProvider] Attempting logout...')
    
    // Предотвращаем повторные инициализации во время logout
    isInitializing = true
    
    try {
      // Сначала очищаем токены на клиенте
      clearAuthTokens()
      setIsAuthenticated(false)

      // Затем делаем запрос на сервер
      const result = await query<{ logout: { success: boolean; message?: string } }>(
        `${location.origin}/graphql`,
        ADMIN_LOGOUT_MUTATION
      )

      console.log('[AuthProvider] Logout response:', result)

      if (result?.logout?.success) {
        console.log('[AuthProvider] Logout successful:', result.logout.message)
        window.location.href = '/login'
      } else {
        console.warn('[AuthProvider] Logout was not successful:', result?.logout?.message)
        // Все равно редиректим на страницу входа
        window.location.href = '/login'
      }
    } catch (error) {
      console.error('[AuthProvider] Logout error:', error)
      // При любой ошибке редиректим на страницу входа
      window.location.href = '/login'
    } finally {
      isInitializing = false
    }
  }

  const value: AuthContextType = {
    isAuthenticated,
    isReady,
    login,
    logout
  }

  console.log('[AuthProvider] Rendering provider with context')
  return <AuthContext.Provider value={value}>{props.children}</AuthContext.Provider>
}

// Export the logout function for direct use
export const logout = async () => {
  console.log('[Auth] Executing standalone logout...')
  try {
    const result = await query<{ logout: AuthSuccess }>(`${location.origin}/graphql`, ADMIN_LOGOUT_MUTATION)
    console.log('[Auth] Standalone logout result:', result)
    if (result?.logout?.success) {
      clearAuthTokens()
      return true
    }
    return false
  } catch (error) {
    console.error('[Auth] Standalone logout error:', error)
    // Даже при ошибке очищаем токены
    clearAuthTokens()
    throw error
  }
}
