
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DerivingStrategies #-}
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
import Data.Swagger hiding (Http)
import Gargantext.API.Admin.Auth.Types (Token)
import Gargantext.API.Auth.PolicyCheck (PolicyChecked)
import Gargantext.Database.Admin.Types.Node ( NodeId (..) )
import GHC.Generics
import Prelude
import Servant.API
import Servant.Client.Core.BaseUrl
import Test.QuickCheck


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 Arbitrary RemoteExportRequest where
  arbitrary = RemoteExportRequest <$> (pure (BaseUrl Http "dev.sub.gargantext.org" 8008 "")) <*> arbitrary

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
