content: {-# LANGUAGE OverloadedStrings #-}
  module Domain.User
      where
  
  import Control.Lens
  import Data.Time
  import Database.Persist
  import Control.Monad.IO.Class
  import Control.Monad.Except
  import Data.Default
  import Models
  import Types
  import Updater
  import DBTypes
  import Operation
  
  dbCreateUser :: UserInput -> App (Either UserCreationError UserID)
  dbCreateUser u = runExceptT $ do
      time <- liftIO getCurrentTime
      let dbu = DBUser { _dBUserFirstName = view firstName u
                       , _dBUserLastName  = view lastName u
                       , _dBUserTenantID  = view tenantID u
                       , _dBUserUsername  = view username u
                       , _dBUserPassword  = view password u
                       , _dBUserEmail     = view email u
                       , _dBUserPhone     = view phone u
                       , _dBUserStatus    = InactiveU
                       , _dBUserCreatedAt = time
                       , _dBUserUpdatedAt = time
                       }
      result <- runDb $ insertUnique dbu
      case result of
           Just a -> return a
           Nothing -> throwError $ UserExists (view username u)
  
  dbUpdateUser :: UserID -> UserUpdater -> OperationT App (Either DBError ())
  dbUpdateUser id uu = requirePermission (EditUser id) >> (runDb $ do
      time <- liftIO $ getCurrentTime
      oldUser' <- get id
      case oldUser' of
           Nothing -> return $ Left $ UserNotFound id
           Just oldUser -> Right <$> replace id (set updatedAt time $ runUpdate uu oldUser))
  
  dbGetUser :: UserID -> OperationT App (Either DBError User)
  dbGetUser uid = runExceptT $ do
      dbu <- ExceptT $ maybe (Left $ UserNotFound uid)
                             Right
                         <$> (runDb $ get uid)
      let u = UserB { _userFirstName = view firstName dbu
                    , _userLastName  = view lastName dbu
                    , _userTenantID  = view tenantID dbu
                    , _userUsername  = view username dbu
                    , _userPassword  = ()
                    , _userEmail     = view email dbu
                    , _userPhone     = view phone dbu
                    , _userStatus    = InactiveU
                    , _userRole      = def
                    , _userUserID    = uid
                    }
      return u
  