import {
  useContext,
  useMemo,
  useCallback,
  createContext,
  useState,
} from 'react'
import * as Auth from 'aws-amplify/auth'

interface AuthContextType {
  authUser: Auth.FetchUserAttributesOutput | null
  signIn: ({
    username,
    password,
  }: {
    username: string
    password: string
  }) => Promise<Auth.SignInOutput>
  signOut: () => Promise<void>
}

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

export function useAuth() {
  return useContext(AuthContext)
}

export function AuthProvider({ children }: { children: React.ReactNode }) {
  const [authUser, setAuthUser] =
    useState<Auth.FetchUserAttributesOutput | null>(null)

  const signIn = useCallback(
    async ({
      username,
      password,
    }: {
      username: string
      password: string
    }): Promise<Auth.SignInOutput> => {
      const signInOut = await Auth.signIn({
        username,
        password,
        options: {
          clientMetadata: {},
        },
      })

      if (signInOut?.isSignedIn) {
        setAuthUser(await Auth.fetchUserAttributes())
      }

      return signInOut
    },
    [],
  )

  const signOut = useCallback(async (): Promise<void> => {
    try {
      return await Auth.signOut()
    } catch {}
  }, [])

  const authContext = useMemo<AuthContextType>(
    () => ({
      authUser,
      signIn,
      signOut,
    }),
    [authUser, signIn, signOut],
  )

  return (
    <AuthContext.Provider value={authContext}>{children}</AuthContext.Provider>
  )
}
