-- SPDX-FileCopyrightText: 2022-2024 Sarah Vaupel <sarah.vaupel@uniworx.de>, Steffen Jost <jost@tcs.ifi.lmu.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later

{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}

module Utils.Users
  ( AuthenticationKind(..)
  , AddUserData(..)
  , addNewUser, addNewUserDB
  ) where

import Import


data AddUserData = AddUserData
  { audTitle            :: Maybe Text
  , audFirstName        :: Text
  , audSurname          :: UserSurname
  , audDisplayName      :: UserDisplayName
  , audDisplayEmail     :: UserEmail
  , audMatriculation    :: Maybe UserMatriculation
  , audSex              :: Maybe Sex
  , audBirthday         :: Maybe Day
  , audMobile           :: Maybe Text 
  , audTelephone        :: Maybe Text   
  , audFPersonalNumber  :: Maybe Text 
  , audFDepartment      :: Maybe Text 
  , audPostAddress      :: Maybe StoredMarkup
  , audPrefersPostal    :: Bool
  , audPinPassword      :: Maybe Text
  , audEmail            :: UserEmail
  , audIdent            :: UserIdent
  , audAuth             :: AuthenticationKind
  }

-- | Adds a new user to database, no background jobs are scheduled, no notifications send
-- Note: `Foundation.Yesod.Auth` contains similar code with potentially differing defaults!
addNewUser :: AddUserData -> Handler (Maybe UserId)
addNewUser aud = do
  udc <- getsYesod $ view _appUserDefaults
  usr <- makeUser udc aud
  runDB $ insertUnique usr

-- | Variant of `addNewUser` which allows for rollback through follwing throws
addNewUserDB :: AddUserData -> DB (Maybe UserId)
addNewUserDB aud = do 
  udc <- liftHandler $ getsYesod $ view _appUserDefaults
  usr <- makeUser udc aud
  insertUnique usr

makeUser :: MonadIO m => UserDefaultConf -> AddUserData -> m User
makeUser UserDefaultConf{..} AddUserData{..} = do
  now <- liftIO getCurrentTime
  UserDefaultConf{..} <- getsYesod $ view _appUserDefaults
  let 
    newUser = User
      { userIdent                   = audIdent
      , userMaxFavourites           = userDefaultMaxFavourites
      , userMaxFavouriteTerms       = userDefaultMaxFavouriteTerms
      , userTheme                   = userDefaultTheme
      , userDateTimeFormat          = userDefaultDateTimeFormat
      , userDateFormat              = userDefaultDateFormat
      , userTimeFormat              = userDefaultTimeFormat
      , userDownloadFiles           = userDefaultDownloadFiles
      , userWarningDays             = userDefaultWarningDays
      , userShowSex                 = userDefaultShowSex
      , userExamOfficeGetSynced     = userDefaultExamOfficeGetSynced
      , userExamOfficeGetLabels     = userDefaultExamOfficeGetLabels
      , userNotificationSettings    = def
      , userLanguages               = Nothing
      , userCsvOptions              = def { csvFormat = review csvPreset CsvPresetXlsx }
      , userTokensIssuedAfter       = Nothing
      , userCreated                 = now
      , userLastLdapSynchronisation = Nothing
      , userLdapPrimaryKey          = audFPersonalNumber
      , userLastAuthentication      = Nothing
      , userEmail                   = audEmail
      , userDisplayName             = audDisplayName
      , userDisplayEmail            = audDisplayEmail
      , userFirstName               = audFirstName
      , userSurname                 = audSurname
      , userTitle                   = audTitle
      , userSex                     = audSex
      , userBirthday                = audBirthday
      , userMobile                  = audMobile
      , userTelephone               = audTelephone
      , userCompanyPersonalNumber   = audFPersonalNumber
      , userCompanyDepartment       = audFDepartment    
      , userPostAddress             = audPostAddress
      , userPostLastUpdate          = Nothing
      , userPrefersPostal           = audPrefersPostal
      , userPinPassword             = audPinPassword
      , userMatrikelnummer          = audMatriculation
      , userLastSync                = Nothing -- TODO: combine add user with external sync?
      }
  runDB $ insertUnique newUser    