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

Count API part of Gargantext.
-}

{-# OPTIONS_GHC -fno-warn-deprecations #-}

{-# LANGUAGE TemplateHaskell    #-}
{-# LANGUAGE TypeOperators      #-}
{-# LANGUAGE DeriveAnyClass     #-}

module Gargantext.API.Search
      where

import Data.Text qualified as T
import Gargantext.API.Prelude (IsGargServer)
import Gargantext.API.Routes.Named.Search qualified as Named
import Gargantext.API.Search.Types (SearchQuery(..), SearchResult(..), SearchResultTypes(..), SearchType(..))
import Gargantext.Core.Text.Corpus.Query (RawQuery (..), parseQuery)
import Gargantext.Core.Types.Query (Limit, Offset)
import Gargantext.Core.Types.Search (toRow)
import Gargantext.Database.Action.Flow.Pairing (isPairedWith)
import Gargantext.Database.Action.Search (searchInCorpus, searchInCorpusWithContacts)
import Gargantext.Database.Admin.Types.Node (NodeId, NodeType(..))
import Gargantext.Database.Prelude
import Gargantext.Database.Query.Facet (OrderBy)
import Gargantext.Prelude
import Gargantext.System.Logging (logLocM, LogLevel(..))
import Servant.Server.Generic (AsServerT)

-----------------------------------------------------------------------
-- TODO-ACCESS: CanSearch? or is it part of CanGetNode
-- TODO-EVENTS: No event, this is a read-only query.
-- | Api search function
api :: IsGargServer env err m => NodeId -> Named.SearchAPI SearchResult (AsServerT m)
api nId = Named.SearchAPI { searchEp = searchEp nId }


searchEp :: IsGargServer env err m
         => NodeId
         -> SearchQuery
         -> Maybe Offset
         -> Maybe Limit
         -> Maybe OrderBy
         -> m SearchResult
searchEp nId (SearchQuery rawQuery SearchDoc) o l order = case parseQuery rawQuery of
  Left  err -> pure $ SearchResult $ SearchNoResult (T.pack err)
  Right q   -> do
    $(logLocM) DEBUG $ T.pack "New search started with query = " <> getRawQuery rawQuery
    (SearchResult <$> SearchResultDoc) . map (toRow nId)
      <$> runDBQuery (searchInCorpus nId False q o l order)
searchEp nId (SearchQuery rawQuery SearchContact) o l order = case parseQuery rawQuery of
  Left  err -> pure $ SearchResult $ SearchNoResult (T.pack err)
  Right q   -> runDBQuery $ do
    -- printDebug "isPairedWith" nId
    aIds <- isPairedWith nId NodeAnnuaire
    -- TODO if paired with several corpus
    case head aIds of
      Nothing  -> pure $ SearchResult
                $ SearchNoResult "[G.A.Search] pair corpus with an Annuaire"
      Just aId -> (SearchResult
              <$> SearchResultContact) . map (toRow aId)
              <$> searchInCorpusWithContacts nId aId q o l order
searchEp _nId (SearchQuery _q SearchDocWithNgrams) _o _l _order = panicTrace "not implemented"                      
