import React, { useState, useContext, createContext, useEffect } from 'react'
import { USERTYPE, BLANKFUNCTION, LOGINDATA, USEREXTRAINFO } from 'data-models'
import { errorToast } from 'ui'
import { useMutation, useQuery, UseMutationResult } from '@tanstack/react-query'
import { extend, find, omit } from 'lodash'
import { toast } from 'react-toastify'
import { AxiosResponse } from 'axios'

import { useNavigate } from 'react-router-dom'
import {
  getAuthorizationMatrixByRoleId,
  getAuthUserDetails,
  loginUserFunc,
  logoutUserApi,
  updateRole,
} from './queries/auth'

export type LoginUserDataType = {
  lskey?: string
  loginUserData: LOGINDATA
}

interface AuthContext {
  isAuthenticated: boolean
  isCheckingAuthentication: boolean
  authUser: USERTYPE
  loginUser: UseMutationResult<AxiosResponse<any, any>, { message: string }, void, unknown>
  authUserExtraInfo: USEREXTRAINFO
  logoutUser: BLANKFUNCTION
  checkAuthentication: BLANKFUNCTION
  selectRole: any
  authorizationMatrix: any[]
}

interface AuthProviderProps {
  children: React.ReactNode | React.ReactElement
}

export const ROLE_TYPE = {
  ADMIN: 1,
  ACCOUNT_MANAGER: 2,
  FIELD_SALES_MANAGER: 3,
  KEY_ACCOUNT_MANAGER: 4,
  TECHNICAL_SUPPORT: 5,
  SERVICER: 6,
  SALES_MANAGER: 7,
  FLEET: 8,
  SERVICE_MANAGER: 9,
  MANAGING_DIRECTOR: 10,
  SALES_SUPPORT: 11,
  USED_TRUCK_SUPPORT: 12,
}

const authContext = createContext<AuthContext>({
  isCheckingAuthentication: false,
  isAuthenticated: false,
  authUser: {} as USERTYPE,
  loginUser: {} as UseMutationResult<AxiosResponse<any, any>, { message: string }, void, unknown>,
  authUserExtraInfo: {} as USEREXTRAINFO,
  logoutUser: () => {},
  checkAuthentication: () => {},
  selectRole: {} as any,
  authorizationMatrix: [],
})

const { Provider } = authContext

const useAuthProvider = () => {
  const navigate = useNavigate()

  const [isAuthenticated, setIsAuthenticated] = useState<boolean>(false)
  const [authorizationMatrix, setAuthorizationMatrix] = useState<any[]>([])
  const [authUser, setAuthUser] = useState<USERTYPE>({} as USERTYPE)
  const [authUserExtraInfo, setAuthUserExtraInfo] = useState<any>({} as USEREXTRAINFO)

  const loginUser = useMutation(['loginUser'], () => loginUserFunc(), {
    onSuccess: (data) => {
      if (data.data) {
        window.location.replace(data.data)
      } else {
        toast.error('Login Failed')
      }
    },
    onError: (error: { message: string }) => {
      toast(error?.message || 'Login failed', errorToast)
    },
  })

  const getAuthorizationMatrix = useMutation(
    ['getAuthorizationMatrix'],
    (roleId: number) => getAuthorizationMatrixByRoleId(roleId),
    {
      onSuccess: (data) => {
        setAuthorizationMatrix(data?.data?.data || [])
      },
      onError: (error: { message: string }) => {
        toast(error?.message || 'Failed to fetch authorization matrix', errorToast)
      },
    },
  )

  const getAuthUserDetail = useMutation(['auth.login_user'], () => getAuthUserDetails(), {
    onSuccess: (data) => {
      const auth = extend(data?.data.user, {
        country: find(data?.data?.country, {
          id: data?.data?.user.country_id,
        }),
        role: data?.data.role,
      })
      setIsAuthenticated(!!data?.data?.user?.id)
      setAuthUser(auth)
      setAuthUserExtraInfo(omit(data?.data, ['user', 'access_token', 'role']))
      getAuthorizationMatrix.mutate(data?.data?.role_id)
    },
    onError: (error: { message: string }) => {
      if (error?.message !== 'Role not found') {
        toast(error?.message || 'Login failed', errorToast)
      }
    },
  })

  const checkAuthentication = () => {
    getAuthUserDetail.mutate()
  }

  const selectRole = useMutation(['auth.select_role'], (roleId: number) => updateRole(roleId), {
    onSuccess: (data: any) => {
      if (data?.data?.link) {
        window.location.replace(data?.data?.link)
      }
    },
    onError: (error: Error) => {
      toast(error?.message || 'Select User failed', errorToast)
    },
  })

  const logoutUserMutation = useMutation(['logoutUser'], () => logoutUserApi(), {
    onSuccess: () => {
      setIsAuthenticated(false)
      setAuthUser({} as USERTYPE)
      setAuthUserExtraInfo({} as USEREXTRAINFO)
      navigate('/login')
    },
    onError: (error: { message: string }) => {
      if (error?.message === 'Session expired. Please login again.') {
        setIsAuthenticated(false)
        setAuthUser({} as USERTYPE)
        setAuthUserExtraInfo({} as USEREXTRAINFO)
        navigate('/login')
      }
      toast(error?.message || 'Logout failed', errorToast)
    },
  })

  const logoutUser = () => {
    logoutUserMutation.mutate()
  }

  useEffect(() => {
    checkAuthentication()
  }, [])

  return {
    isCheckingAuthentication: getAuthUserDetail.isLoading || false,
    isAuthenticated,
    authUser,
    authUserExtraInfo,
    loginUser,
    logoutUser,
    checkAuthentication,
    selectRole,
    authorizationMatrix,
  }
}

export const AuthProvider = ({ children }: AuthProviderProps) => {
  const auth = useAuthProvider()
  return <Provider value={auth}>{children}</Provider>
}

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