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

{-# OPTIONS_GHC -fno-warn-unused-matches #-}

{-# LANGUAGE AllowAmbiguousTypes     #-}
{-# LANGUAGE IncoherentInstances #-}

module Gargantext.API.Node.File where

import Data.MIME.Types qualified as DMT
import Data.Text qualified as T
import Gargantext.API.Admin.Auth.Types ( AuthenticatedUser, auth_user_id )
import Gargantext.API.Admin.EnvTypes (Env)
import Gargantext.API.Errors.Types ( BackendInternalError )
import Gargantext.API.Node.File.Types
import Gargantext.API.Node.Types ( NewWithFile(NewWithFile) )
import Gargantext.API.Prelude ( GargM )
import Gargantext.API.Routes.Named.File qualified as Named
import Gargantext.API.Worker (serveWorkerAPI)
import Gargantext.Core.Worker.Jobs.Types qualified as Jobs
import Gargantext.Database.Action.Flow.Types ( FlowCmdM )
import Gargantext.Database.Action.Node (mkNodeWithParent)
import Gargantext.Database.Admin.Types.Hyperdata.File ( HyperdataFile(..) )
import Gargantext.Database.Admin.Types.Node ( NodeId, NodeType(..) )
import Gargantext.Database.GargDB qualified as GargDB
import Gargantext.Database.Query.Table.Node (getNodeWith)
import Gargantext.Database.Query.Table.Node.UpdateOpaleye (updateHyperdata)
import Gargantext.Database.Schema.Node (node_hyperdata)
import Gargantext.Database.Prelude
import Gargantext.Prelude
import Gargantext.Utils.Jobs.Monad (MonadJobStatus(..))
import Servant
import Servant.Server.Generic (AsServerT)
import Control.Lens (view)
import Gargantext.Core.Config (hasConfig)


fileApi :: (FlowCmdM env err m)
        => NodeId
        -> m (Headers '[Servant.Header "Content-Type" Text] BSResponse)
fileApi nId = fileDownload nId

fileDownload :: (FlowCmdM env err m)
             => NodeId
             -> m (Headers '[Servant.Header "Content-Type" Text] BSResponse)
fileDownload nId = do
  -- printDebug "[fileDownload] uId" uId
  -- printDebug "[fileDownload] nId" nId

  node <- runDBQuery $ getNodeWith nId (Proxy :: Proxy HyperdataFile)
  let (HyperdataFile { _hff_name = name'
                     , _hff_path = path }) = node ^. node_hyperdata

  Contents c <- GargDB.readGargFile $ T.unpack path

  let (mMime, _) = DMT.guessType DMT.defaultmtd False $ T.unpack name'
      mime = fromMaybe "text/plain" mMime

  pure $ addHeader (T.pack mime) $ BSResponse c
 
  --pure c

  -- let settings = embeddedSettings [("", encodeUtf8 c)]

  -- Tagged $ staticApp settings

  -- let settings = embeddedSettings [("", "hello")]
  -- Tagged $ staticApp settings
fileAsyncApi :: AuthenticatedUser
             -- ^ The logged-in user
             -> NodeId
             -> Named.FileAsyncAPI (AsServerT (GargM Env BackendInternalError))
fileAsyncApi authenticatedUser nId =
  Named.FileAsyncAPI {
    addFileAsyncEp = serveWorkerAPI $ \i ->
        Jobs.AddWithFile { _awf_args = i
                         , _awf_node_id = nId
                         , _awf_authenticatedUser = authenticatedUser }
    }


addWithFile :: (FlowCmdM env err m, MonadJobStatus m)
            => AuthenticatedUser
            -- ^ The logged-in user
            -> NodeId
            -> NewWithFile
            -> JobHandle m
            -> m ()
addWithFile authenticatedUser nId nwf@(NewWithFile _d _l fName) jobHandle = do
  cfg <- view hasConfig
  -- printDebug "[addWithFile] Uploading file: " nId
  markStarted 1 jobHandle

  fPath <- GargDB.writeFile nwf
  -- printDebug "[addWithFile] File saved as: " fPath

  runDBTx $ do
    nIds <- mkNodeWithParent cfg NodeFile (Just nId) userId fName

    case nIds of
      [nId'] -> do
        node <- getNodeWith nId' (Proxy :: Proxy HyperdataFile)
        let hl = node ^. node_hyperdata
        void $ updateHyperdata nId' $ hl { _hff_name = fName
                                         , _hff_path = T.pack fPath }

        -- printDebug "[addWithFile] Created node with id: " nId'
        pure ()
      _ -> pure ()

  -- printDebug "[addWithFile] File upload finished: " nId
  markComplete jobHandle
  where
    userId = authenticatedUser ^. auth_user_id

