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

-}


{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# LANGUAGE TemplateHaskell    #-}
{-# LANGUAGE TypeOperators      #-}

module Gargantext.API.Admin.Orchestrator.Types
  where

import Data.Aeson (genericParseJSON, genericToJSON, object, withObject, (.=), (.:), (.:?), Value(String))
import Data.Aeson.Types (unexpected)
import Data.Morpheus.Types ( GQLType(..), DropNamespace(..), typeDirective )
import Data.Swagger (ToSchema, URL, declareNamedSchema, defaultSchemaOptions, genericDeclareNamedSchemaUnrestricted)
-- import Gargantext.API.GraphQL.UnPrefix qualified as GQLU
import Gargantext.Core.Types (TODO(..))
import Gargantext.Core.Utils.Aeson (jsonOptions)
import Gargantext.Prelude
import PUBMED.Types qualified as PUBMED


type EPOAPIToken = Text
type EPOAPIUser = Text

------------------------------------------------------------------------
-- | Main Types
-- TODO IsidoreAuth
data ExternalAPIs = OpenAlex
                  | PubMed (Maybe PUBMED.APIKey)
                  | Arxiv
                  | HAL
                  | IsTex
                  | Isidore
                  | EPO (Maybe EPOAPIUser) (Maybe EPOAPIToken)
  deriving (Show, Eq, Generic)


-- | Main Instances
instance FromJSON ExternalAPIs where
  parseJSON = withObject "ExternalAPIs" $ \o -> do
    db <- o .: "db"
    case db of
      "OpenAlex" -> pure OpenAlex
      "PubMed" -> do
        mAPIKey <- o .:? "api_key"
        pure $ PubMed mAPIKey
      "Arxiv" -> pure Arxiv
      "HAL" -> pure HAL
      "IsTex" -> pure IsTex
      "Isidore" -> pure Isidore
      "EPO" -> do
        mAPIUser <- o .:? "api_user"
        mAPIToken <- o .:? "api_token"
        pure $ EPO mAPIUser mAPIToken
      s -> unexpected (String s)
instance ToJSON ExternalAPIs where
  toJSON (PubMed mAPIKey) = object [ "db" .= toJSON ("PubMed" :: Text)
                                   , "api_key" .= toJSON mAPIKey ]
  toJSON (EPO mAPIUser mAPIToken) = object [ "db" .= toJSON ("EPO" :: Text)
                                           , "api_user" .= toJSON mAPIUser
                                           , "api_token" .= toJSON mAPIToken ]
  toJSON t = object [ "db" .= toJSON (show t :: Text) ]

externalAPIs :: [ExternalAPIs]
externalAPIs =
  [ OpenAlex
  , PubMed Nothing
  , Arxiv
  , HAL
  , IsTex
  , Isidore
  , EPO Nothing Nothing ]

instance ToSchema ExternalAPIs where
  declareNamedSchema = genericDeclareNamedSchemaUnrestricted defaultSchemaOptions

instance ToSchema URL where
  declareNamedSchema _ = declareNamedSchema (Proxy :: Proxy TODO)


data ScraperEvent = ScraperEvent
  { _scev_message :: !(Maybe Text)
  , _scev_level   :: !(Maybe Text)
  , _scev_date    :: !(Maybe Text)
  }
  deriving (Show, Generic, Eq)
instance ToJSON ScraperEvent where
  toJSON = genericToJSON $ jsonOptions "_scev_"
instance FromJSON ScraperEvent where
  parseJSON = genericParseJSON $ jsonOptions "_scev_"
instance ToSchema ScraperEvent  -- TODO _scev_ prefix
instance GQLType ScraperEvent where
  directives _ = typeDirective DropNamespace { dropNamespace = "_scev_" }


data JobLog = JobLog
  { _scst_succeeded :: !(Maybe Int)
  , _scst_failed    :: !(Maybe Int)
  , _scst_remaining :: !(Maybe Int)
  , _scst_events    :: !(Maybe [ScraperEvent])
  }
  deriving (Show, Generic, Eq)

makeLenses ''JobLog

noJobLog :: JobLog
noJobLog = JobLog Nothing Nothing Nothing Nothing

instance ToJSON JobLog where
  toJSON = genericToJSON $ jsonOptions "_scst_"
instance FromJSON JobLog where
  parseJSON = genericParseJSON $ jsonOptions "_scst_"
instance ToSchema JobLog -- TODO _scst_ prefix
instance GQLType JobLog where
  directives _ = typeDirective DropNamespace { dropNamespace = "_scst_" }
