import React, { createContext, useContext, useState } from 'react'
import { message } from 'antd'
import { useHistory } from 'react-router'
import { Account, User, uuid } from '../types'
import { useAppContext } from './AppContext'
import { logOut } from '../api'

type Props = {
  children: React.ReactNode
}

type Context = {
  user: User | null
  accounts: Account[] | null
  selectedAccount: Account | null
  handleLogin: (name: string, password: string) => void
  handleLogout: () => void
  handleSelectAccount: (id: uuid) => void
}

const UserContext = createContext<Context | null>(null)

export const UserContextProvider = ({ children }: Props) => {
  const api = useAppContext()
  const history = useHistory()

  const [user, setUser] = useState<User | null>(null)
  const [accounts, setAccounts] = useState<Account[] | null>(null)
  const [selectedAccount, setSelectedAccount] = useState<Account | null>(null)

  const handleLogin = async (name: string, password: string) => {
    try {
      const { id } = await api.post<any, { id: string }>('/login', {
        name,
        password,
      })
      if (!id) throw new Error('Problem logging in!')
      const user = await api.get<User>(`/users/${id}`)

      if (!user) message.error(`Couldn't find user`)
      setUser(user)

      const accounts = await api.get<Account[]>('/accounts')
      setAccounts(accounts)

      message.success(`logged in as ${user?.name}`, 0.5)
    } catch (err) {
      message.error('Login Failed!')
    }
  }

  const handleLogout = async () => {
    await logOut()
    setUser(null)
    message.success('logged out!', 0.5)
    history.push('/')
  }

  const handleSelectAccount = (id: string) => {
    const account = accounts?.find((account) => account.id === id)
    if (account) setSelectedAccount(account)
  }

  return (
    <UserContext.Provider
      value={{
        user,
        accounts,
        handleLogin,
        handleLogout,
        selectedAccount,
        handleSelectAccount,
      }}
    >
      {children}
    </UserContext.Provider>
  )
}

export const useUserContext = () => {
  const context = useContext(UserContext)

  if (!context)
    throw new Error(
      'UserContext must be called from within the UserContextProvider',
    )

  return context
}
