
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeFamilies #-}

module Gargantext.API.Routes.Named.Private (
  -- * Routes types
    GargPrivateAPI(..)
  , MkProtectedAPI
  , GargPrivateAPI'(..)
  , GargAdminAPI(..)
  , NodeAPIEndpoint(..)
  , MembersAPI(..)
  , AnnuaireAPIEndpoint(..)
  , CorpusAPIEndpoint(..)
  ) where


import Data.Text (Text)
import GHC.Generics
import Gargantext.API.Admin.Auth.Types
import Gargantext.API.Auth.PolicyCheck
import Gargantext.API.Routes.Named.Contact
import Gargantext.API.Routes.Named.Context
import Gargantext.API.Routes.Named.Corpus
import Gargantext.API.Routes.Named.Count
import Gargantext.API.Routes.Named.Document
import Gargantext.API.Routes.Named.List qualified as List
import Gargantext.API.Routes.Named.Node
import Gargantext.API.Routes.Named.Share
import Gargantext.API.Routes.Named.Table
import Gargantext.API.Routes.Named.Tree
import Gargantext.API.Routes.Named.Viz
import Gargantext.Database.Admin.Types.Hyperdata.Any
import Gargantext.Database.Admin.Types.Hyperdata.Corpus
import Gargantext.Database.Admin.Types.Node
import Servant.API
import Servant.Auth qualified as SA


type MkProtectedAPI private = SA.Auth '[SA.JWT, SA.Cookie] AuthenticatedUser :> private


newtype GargPrivateAPI mode = GargPrivateAPI
  { mkPrivateAPI :: mode :- MkProtectedAPI (NamedRoutes GargPrivateAPI')
  } deriving Generic


data GargPrivateAPI' mode = GargPrivateAPI'
  { gargAdminAPI :: mode :- NamedRoutes GargAdminAPI
  , nodeEp       :: mode :- NamedRoutes NodeAPIEndpoint
  , contextEp    :: mode :- "context"  :> Summary "Context endpoint"
                                       :> Capture "node_id" ContextId
                                       :> NamedRoutes (ContextAPI HyperdataAny)
  , corpusNodeAPI :: mode :- NamedRoutes CorpusAPIEndpoint
  , corpusNodeNodeAPI :: mode :- "corpus" :> Summary "Corpus endpoint"
                                          :> Capture "node1_id" NodeId
                                          :> "document"
                                          :> Capture "node2_id" NodeId
                                          :> NamedRoutes (NodeNodeAPI HyperdataAny)
  , corpusExportAPI :: mode :- "corpus" :> Capture "node_id" CorpusId
                                        :> NamedRoutes CorpusExportAPI
  , annuaireEp :: mode :- NamedRoutes AnnuaireAPIEndpoint
  , contactAPI :: mode :- "annuaire" :> Summary "Contact endpoint"
                                     :> Capture "annuaire_id" NodeId
                                     :> NamedRoutes ContactAPI
  , tableNgramsAPI :: mode :- "document" :> Summary "Document endpoint"
                                         :> Capture "doc_id" DocId
                                         :> "ngrams"
                                         :> NamedRoutes TableNgramsAPI
  , documentExportAPI :: mode :- "texts" :> Capture "node_id" DocId
                                         :> NamedRoutes DocumentExportAPI
  , phyloExportAPI    :: mode :- "phylo" :> Capture "node_id" DocId
                                         :> NamedRoutes PhyloExportAPI
  , countAPI :: mode :- "count" :> Summary "Count endpoint"
                                :> ReqBody '[JSON] Query
                                :> NamedRoutes CountAPI
  , graphAPI :: mode :- "graph" :> Summary "Graph endpoint"
                                :> Capture "graph_id" NodeId
                                :> NamedRoutes GraphAPI
  , treeAPI :: mode :- "tree" :> Summary "Tree endpoint"
                              :> Capture "tree_id" NodeId
                              :> PolicyChecked (NamedRoutes NodeTreeAPI)
  , treeFlatAPI :: mode :- "treeflat" :> Summary "Flat tree endpoint"
                                      :> Capture "tree_id" NodeId
                                      :> NamedRoutes TreeFlatAPI
  , membersAPI     :: mode :- "members" :> Summary "Team node members" :> NamedRoutes MembersAPI
  , addWithFormAPI :: mode :- NamedRoutes AddWithForm
  , addWithQueryEp :: mode :- NamedRoutes AddWithQuery
  , listGetAPI     :: mode :- NamedRoutes List.GETAPI
  , listJsonAPI    :: mode :- NamedRoutes List.JSONAPI
  , listTsvAPI     :: mode :- NamedRoutes List.TSVAPI
  , shareUrlAPI    :: mode :- "shareurl" :> NamedRoutes ShareURL
  } deriving Generic


data GargAdminAPI mode = GargAdminAPI
  { rootsEp       :: mode :- "user"  :> Summary "First user endpoint" :> NamedRoutes Roots
  , adminNodesAPI :: mode :- "nodes" :> Summary "Nodes endpoint"
                                     :> ReqBody '[JSON] [NodeId]
                                     :> NamedRoutes NodesAPI
  } deriving Generic

-- | The 'Node' API, unlike the ones for annuaire and corpus,
-- have other endpoints which should not be shared in the hierarchy,
-- like the /freeze/ one. Similarly, a 'Corpus' API will have a
-- '/publish' endpoint that doesn't generalise to everything.
data NodeAPIEndpoint mode = NodeAPIEndpoint
  { nodeEndpointAPI :: mode :- "node"
                            :> Summary "Node endpoint"
                            :> Capture "node_id" NodeId
                            :> NamedRoutes (NodeAPI HyperdataAny)
  } deriving Generic

newtype AnnuaireAPIEndpoint mode = AnnuaireAPIEndpoint
  { annuaireEndpointAPI :: mode :- "annuaire"
                        :> Summary "Annuaire endpoint"
                        :> Capture "annuaire_id" NodeId
                        :> NamedRoutes (NodeAPI HyperdataAnnuaire)
  } deriving Generic

newtype CorpusAPIEndpoint mode = CorpusAPIEndpoint
  { corpusEndpointAPI :: mode :- "corpus"
                      :> Summary "Corpus endpoint"
                      :> Capture "corpus_id" NodeId
                      :> NamedRoutes (NodeAPI HyperdataCorpus)
  } deriving Generic

newtype MembersAPI mode = MembersAPI
  { getMembersEp :: mode :- Get '[JSON] [Text]
  } deriving Generic

