{-|
Module      : Init.hs
Description : Gargantext Init Script
Copyright   : (c) CNRS, 2017-Present
License     : AGPL + CECILL v3
Maintainer  : team@gargantext.org
Stability   : experimental
Portability : POSIX

Initialise the Gargantext dataset.

 -}

{-# LANGUAGE Strict            #-}

module CLI.Init where

import CLI.Parsers
import CLI.Types
import Data.List.NonEmpty qualified as NE
import Gargantext.API.Dev (withDevEnv, runCmdDev)
import Gargantext.API.Errors.Types
import Gargantext.API.Node () -- instances only
import Gargantext.Core.Config (GargConfig(..))
import Gargantext.Core.Config.Types (SecretsConfig(..))
import Gargantext.Core.Config.Utils (readConfig)
import Gargantext.Core.Types.Individu (User(..), arbitraryNewUsers, NewUser(..), arbitraryUsername, GargPassword(..))
import Gargantext.Database.Action.Flow (getOrMkRoot, getOrMkRootWithCorpus)
import Gargantext.Database.Admin.Trigger.Init (initFirstTriggers, initLastTriggers)
import Gargantext.Database.Admin.Types.Hyperdata (HyperdataCorpus)
import Gargantext.Database.Admin.Types.Node
import Gargantext.Database.Prelude (DBCmd')
import Gargantext.Database.Prelude (DBCmd)
import Gargantext.Database.Query.Table.Node (getOrMkList)
import Gargantext.Database.Query.Table.User (insertNewUsers, )
import Gargantext.Database.Query.Tree.Root (MkCorpusUser(MkCorpusUserMaster))
import Gargantext.Prelude
import Options.Applicative


initCLI :: InitArgs -> IO ()
initCLI (InitArgs settingsPath) = do
  putStrLn ("Enter master user (gargantua) _password_ :" :: Text)
  password  <- getLine

  putStrLn ("Enter master user (gargantua) _email_ :" :: Text)
  email     <- getLine

  cfg       <- readConfig         settingsPath
  let secret = _s_secret_key $ _gc_secrets cfg

  let createUsers :: forall env. DBCmd' env BackendInternalError Int64
      createUsers = insertNewUsers (NewUser "gargantua" (cs email) (GargPassword $ cs password)
                                   NE.:| arbitraryNewUsers
                                   )

  let
    mkRoots :: forall env. DBCmd' env BackendInternalError [(UserId, RootId)]
    mkRoots = mapM getOrMkRoot $ map UserName ("gargantua" : arbitraryUsername)
    -- TODO create all users roots

  let
    initMaster :: forall env. DBCmd' env BackendInternalError (UserId, RootId, CorpusId, ListId)
    initMaster = do
      (masterUserId, masterRootId, masterCorpusId)
                  <- getOrMkRootWithCorpus MkCorpusUserMaster
                                            (Nothing :: Maybe HyperdataCorpus)
      masterListId <- getOrMkList masterCorpusId masterUserId
      _triggers    <- initLastTriggers masterListId
      pure (masterUserId, masterRootId, masterCorpusId, masterListId)

  withDevEnv settingsPath $ \env -> do
    _ <- runCmdDev env (initFirstTriggers secret :: DBCmd BackendInternalError [Int64])
    _ <- runCmdDev env createUsers
    x <- runCmdDev env initMaster
    _ <- runCmdDev env mkRoots
    putStrLn (show x :: Text)

initCmd :: HasCallStack => Mod CommandFields CLI
initCmd = command "init" (info (helper <*> fmap CLISub init_p) (progDesc "Initialise this Gargantext instance."))

init_p :: Parser CLICmd
init_p = fmap CCMD_init $ InitArgs
  <$> settings_p