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

-}


{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE TypeOperators #-}

module Gargantext.API.Routes.Named.Remote (
  -- * Routes types
    RemoteExportAPI(..)
  , RemoteImportAPI(..)
  , RemoteExportRequest(..)
  , RemoteBinaryData(..)
  ) where

import Conduit qualified as C
import Data.Aeson as JSON
import Data.ByteString.Lazy qualified as BL
import Data.ByteString qualified as BS
import Data.Proxy (Proxy(Proxy))
import Data.Swagger (NamedSchema(..), ToSchema, declareNamedSchema, binarySchema, sketchStrictSchema)
import Gargantext.API.Admin.Auth.Types (Token)
import Gargantext.API.Auth.PolicyCheck (PolicyChecked)
import Gargantext.Database.Admin.Types.Node ( NodeId (..) )
import GHC.Generics (Generic)
import Prelude
import Servant.API
import Servant.Client.Core.BaseUrl (BaseUrl(..), parseBaseUrl, Scheme(Http))


data RemoteExportAPI mode = RemoteExportAPI
  { remoteExportEp :: mode :- "remote" :> ReqBody '[JSON] RemoteExportRequest :> PolicyChecked (Post '[JSON] [NodeId])
  } deriving Generic

data RemoteImportAPI mode = RemoteImportAPI
  { remoteImportEp :: mode :- "import" :> StreamBody NoFraming OctetStream (C.ConduitT () RemoteBinaryData IO ())
                                       :> Post '[JSON] [NodeId]
  } deriving Generic

data RemoteExportRequest =
  RemoteExportRequest
  { -- | The URL of the instance we want to copy data to.
    _rer_instance_url  :: BaseUrl
    -- | The JWT token to use for authentication purposes.
  , _rer_instance_auth :: Token
  } deriving (Show, Eq, Generic)

instance ToJSON RemoteExportRequest where
  toJSON RemoteExportRequest{..}
    = JSON.object [ "instance_url"  .= toJSON _rer_instance_url
                  , "instance_auth" .= toJSON _rer_instance_auth
                  ]

instance FromJSON RemoteExportRequest where
  parseJSON = withObject "RemoteExportRequest" $ \o -> do
    _rer_instance_url  <- maybe (fail "RemoteExportRequest invalid URL") pure =<< (parseBaseUrl <$> o .: "instance_url")
    _rer_instance_auth <- o .: "instance_auth"
    pure RemoteExportRequest{..}

instance ToSchema RemoteExportRequest where
  declareNamedSchema _ =
    let exampleSchema = RemoteExportRequest (BaseUrl Http "dev.sub.gargantext.org" 8008 "") ("abcdef")
    in pure $ NamedSchema (Just "RemoteExportRequest") $ sketchStrictSchema exampleSchema

newtype RemoteBinaryData = RemoteBinaryData { getRemoteBinaryData :: BS.ByteString }
  deriving (Show, Eq, Ord)

instance Accept RemoteBinaryData where
  contentType _ = contentType (Proxy :: Proxy OctetStream)

instance MimeRender OctetStream RemoteBinaryData where
    mimeRender _ (RemoteBinaryData bs) = BL.fromStrict bs

instance MimeUnrender OctetStream RemoteBinaryData where
    mimeUnrender _ bs = Right (RemoteBinaryData $ BS.toStrict bs)

instance ToSchema RemoteBinaryData where
  declareNamedSchema _ = pure $ NamedSchema (Just "RemoteExportRequest") binarySchema
