{-|
Module      : Gargantext.API.Worker
Description : New-style Worker API (no more servant-job)
Copyright   : (c) CNRS, 2024-Present
License     : AGPL + CECILL v3
Maintainer  : team@gargantext.org
Stability   : experimental
Portability : POSIX

-}

{-# LANGUAGE TypeOperators #-}

module Gargantext.API.Worker where

import Data.Aeson qualified as JSON
import Data.ByteString.Lazy qualified as BL
import Data.Text.Encoding qualified as TE
import Gargantext.API.Prelude (IsGargServer)
import Gargantext.Core.Worker.Jobs (sendJob)
import Gargantext.Core.Worker.Jobs.Types (Job(..), getWorkerMNodeId)
import Gargantext.Core.Worker.Types (JobInfo(..))
import Gargantext.Prelude
import Gargantext.System.Logging (logM, LogLevel(..))
import Servant.API ((:>), (:-), JSON, Post, ReqBody)
import Servant.Server.Generic (AsServerT)


data WorkerAPI contentType input mode = WorkerAPI
  { workerAPIPost :: mode :- ReqBody contentType input
                          :> Post '[JSON] JobInfo }
  deriving Generic


serveWorkerAPI :: IsGargServer env err m
               => (input -> Job)
               -> WorkerAPI contentType input (AsServerT m)
serveWorkerAPI f = serveWorkerAPIM (pure . f)

serveWorkerAPIM :: IsGargServer env err m
                => (input -> m Job)
                -> WorkerAPI contentType input (AsServerT m)
serveWorkerAPIM mkJob = WorkerAPI { workerAPIPost }
  where
    workerAPIPost i = do
      job <- mkJob i
      logM DEBUG $ "[serveWorkerAPI] sending job " <> TE.decodeUtf8 (BL.toStrict $ JSON.encode job)
      mId <- sendJob job
      pure $ JobInfo { _ji_message_id = mId
                     , _ji_mNode_id = getWorkerMNodeId job }

serveWorkerAPIEJob :: (MonadError err m, IsGargServer env err m)
                   => (input -> Either err Job)
                   -> WorkerAPI contentType input (AsServerT m)
serveWorkerAPIEJob f = WorkerAPI { workerAPIPost }
  where
    workerAPIPost i = do
      let eJob = f i
      case eJob of
        Left err -> throwError err
        Right job -> do
          mId <- sendJob job
          pure $ JobInfo { _ji_message_id = mId
                         , _ji_mNode_id = getWorkerMNodeId job }
