// Zależności
import { FC, createContext, ReactElement, useState, useEffect } from 'react'
import { useCookies } from 'react-cookie'
import { getGraphQlError, redirectTo, getDebug } from '@contentpi/lib'
import { useQuery, useMutation } from '@apollo/client'

// Przekształcenia
import LOGIN_MUTATION from '../graphql/user/login.mutation'

// Zapytania
import GET_USER_DATA_QUERY from '../graphql/user/getUserData.query'

// Interfejsy
interface IUserContext {
  login(input: any): any
  connectedUser: any
}

interface IProps {
  page?: string
  children: ReactElement
}

// Tworzenie kontekstu
export const UserContext = createContext<IUserContext>({
  login: () => null,
  connectedUser: null
})

const UserProvider: FC<IProps> = ({ page = '', children }): ReactElement => {
  const [cookies, setCookie] = useCookies()
  const [connectedUser, setConnectedUser] = useState(null)

  // Przekształcenia
  const [loginMutation] = useMutation(LOGIN_MUTATION)

  // Zapytania
  const { data: dataUser } = useQuery(GET_USER_DATA_QUERY, {
    variables: {
      at: cookies.at || ''
    }
  })

  // Efekty
  useEffect(() => {
    if (dataUser) {
      if (!dataUser.getUserData.id && page !== 'login') {
        // Jeśli sesja użytkownika jest niepoprawna i dotyczy innej strony niż strona logowania,
        // użytkownik jest do niej przekierowywany
        redirectTo('/login?redirectTo=/dashboard', false)
      } else {
        // Jeśli dostępne są dane użytkownika, zapisywane są w stanie connectedUser
        setConnectedUser(dataUser.getUserData)
      }
    }
  }, [dataUser, page])

  async function login(input: { email: string; password: string }): Promise<any> {
    try {
      // Zastosowanie przekształcenia loginMutation przekazującego adres e-mail i hasło
      const { data: dataLogin } = await loginMutation({
        variables: {
          email: input.email,
          password: input.password
        }
      })

      if (dataLogin) {
        // Jeśli logowanie powiodło się, token zapisywany jest w informacjach cookie tokenu at
        setCookie('at', dataLogin.login.token, { path: '/' })

        return dataLogin.login.token
      }
    } catch (err) {
      // W wypadku wystąpienia błędu jest on zwracany
      return getGraphQlError(err)
    }
  }

  // Eksportowanie kontekstu
  const context = {
    login,
    connectedUser
  }

  return <UserContext.Provider value={context}>{children}</UserContext.Provider>
}

export default UserProvider
