// ** React Imports
import { createContext, useEffect, useState, ReactNode } from 'react'

// ** Next Import
import { useRouter } from 'next/router'

// ** Axios
import axios from 'axios'
import axiosConfig from 'src/configs/axiosConfig';
// ** Config
import authConfig from 'src/configs/auth'
import { deleteCookie, getCookie, setCookie } from 'cookies-next';
// ** Types
import { AuthValuesType, LoginParams, ErrCallbackType, UserDataType } from './types'
import UserRole from 'src/constant/UserRole'
import COMPANY_ID from 'src/constant/constant';
import { useAuth } from 'src/hooks/useAuth'
// ** Defaults
const defaultProvider: AuthValuesType = {
  user: null,
  loading: true,
  setUser: () => null,
  setLoading: () => Boolean,
  login: () => Promise.resolve(),
  logout: () => Promise.resolve()
}

const AuthContext = createContext(defaultProvider)

type Props = {
  children: ReactNode
}

const AuthProvider = ({ children }: Props) => {
  // ** States
  const [user, setUser] = useState<UserDataType | null>(defaultProvider.user)
  const [loading, setLoading] = useState<boolean>(defaultProvider.loading)

  // ** Hooks
  const router = useRouter()
  const auth = useAuth()

  useEffect(() => {
    const initAuth = async (): Promise<void> => {
      const storedToken = getCookie('accessToken')!

      if (storedToken) {
        setLoading(true)
        axiosConfig
          .post(process.env.NEXT_PUBLIC_API_URL+ '/me')
          .then(async response => {
            setLoading(false)
            let userData = {
              id : response.data.user.id,
              username: response.data.user.name,
              role : response.data.user.roles[0],
            }
            
            setUser({ ...userData })
          })
          .catch((err) => {
            localStorage.removeItem('userData')
            deleteCookie('accessToken')
            setUser(null)
            setLoading(false)
            if (authConfig.onTokenExpiration === 'logout' && !router.pathname.includes('login')) {
              router.replace('/login')
            }
          })
      } else {
        setLoading(false)
      }
    }
    
    initAuth()
  }, [])

  const handleLogin = (params: LoginParams, errorCallback?: ErrCallbackType) => {
    axios
    .post(process.env.NEXT_PUBLIC_API_URL+ '/login', params)
    .then(async response => {
      setCookie('accessToken', response.data['api-token'])
      const returnUrl = router.query.returnUrl
      const redirectURL = returnUrl && returnUrl !== '/' ? returnUrl : '/'

      let userData = {
        id : response.data.user.id,
        username: response.data.user.name,
        role : response.data.user.roles[0],
      }
      setUser({...userData})
      window.localStorage.setItem('userData', JSON.stringify(userData))
      
      if (userData.role == UserRole.GROUP_ADMIN) {
        deleteCookie(COMPANY_ID)
        router.replace('/select-company')
      } else {
        router.replace(redirectURL as string)
      }
    })
    .catch(err => {
      if (errorCallback) errorCallback(err)
    })
  }

  const handleLogout = () => {
    setUser(null)
    window.localStorage.removeItem('userData')
    deleteCookie('accessToken')
    router.push('/login')
  }

  const values = {
    user,
    loading,
    setUser,
    setLoading,
    login: handleLogin,
    logout: handleLogout
  }

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

export { AuthContext, AuthProvider }
