module Galley.API.Public.TeamNotification where

import Data.Id
import Data.Range
import Data.UUID.Util qualified as UUID
import Galley.API.Teams.Notifications qualified as APITeamQueue
import Galley.App
import Galley.Effects
import Imports
import Polysemy
import Wire.API.Error
import Wire.API.Error.Galley
import Wire.API.Internal.Notification
import Wire.API.Routes.API
import Wire.API.Routes.Public.Galley.TeamNotification

teamNotificationAPI :: API TeamNotificationAPI GalleyEffects
teamNotificationAPI :: API TeamNotificationAPI GalleyEffects
teamNotificationAPI =
  forall {k} (name :: k) (r0 :: EffectRow) api.
(HasServer api '[Domain],
 ServerEffects (DeclaredErrorEffects api) r0) =>
ServerT api (Sem (Append (DeclaredErrorEffects api) r0))
-> API (Named name api) r0
forall (name :: Symbol) (r0 :: EffectRow) api.
(HasServer api '[Domain],
 ServerEffects (DeclaredErrorEffects api) r0) =>
ServerT api (Sem (Append (DeclaredErrorEffects api) r0))
-> API (Named name api) r0
mkNamedAPI @"get-team-notifications" ServerT
  (Summary "Read recently added team members from team queue"
   :> (Description GetTeamNotificationsDescription
       :> ("teams"
           :> ("notifications"
               :> (ZUser
                   :> (CanThrow 'TeamNotFound
                       :> (CanThrow 'InvalidTeamNotificationId
                           :> (QueryParam'
                                 '[Optional, Strict,
                                   Description
                                     "Notification id to start with in the response (UUIDv1)"]
                                 "since"
                                 NotificationId
                               :> (QueryParam'
                                     '[Optional, Strict,
                                       Description
                                         "Maximum number of events to return (1..10000; default: 1000)"]
                                     "size"
                                     (Range 1 10000 Int32)
                                   :> Get '[JSON] QueuedNotificationList)))))))))
  (Sem
     (Append
        (DeclaredErrorEffects
           (Summary "Read recently added team members from team queue"
            :> (Description GetTeamNotificationsDescription
                :> ("teams"
                    :> ("notifications"
                        :> (ZUser
                            :> (CanThrow 'TeamNotFound
                                :> (CanThrow 'InvalidTeamNotificationId
                                    :> (QueryParam'
                                          '[Optional, Strict,
                                            Description
                                              "Notification id to start with in the response (UUIDv1)"]
                                          "since"
                                          NotificationId
                                        :> (QueryParam'
                                              '[Optional, Strict,
                                                Description
                                                  "Maximum number of events to return (1..10000; default: 1000)"]
                                              "size"
                                              (Range 1 10000 Int32)
                                            :> Get '[JSON] QueuedNotificationList))))))))))
        '[BrigAccess, SparAccess, NotificationSubsystem, GundeckAPIAccess,
          Rpc, ExternalAccess, FederatorAccess,
          BackendNotificationQueueAccess, BotAccess, FireAndForget,
          ClientStore, CodeStore, ProposalStore, ConversationStore,
          SubConversationStore, Random, CustomBackendStore, TeamFeatureStore,
          LegalHoldStore, MemberStore, SearchVisibilityStore, ServiceStore,
          TeamNotificationStore, TeamStore, TeamMemberStore InternalPaging,
          TeamMemberStore CassandraPaging, ListItems CassandraPaging ConvId,
          ListItems CassandraPaging (Remote ConvId),
          ListItems LegacyPaging ConvId, ListItems LegacyPaging TeamId,
          ListItems InternalPaging TeamId, Input AllTeamFeatures,
          Input (Maybe [TeamId], FeatureDefaults LegalholdConfig),
          Input (Local ()), Input Opts, Input UTCTime, Queue DeleteItem,
          Logger (Msg -> Msg), Error DynError, Input ClientState, Input Env,
          Error InvalidInput, Error InternalError, Error FederationError,
          Async, Delay, Fail, Embed IO, Error JSONResponse, Resource,
          Final IO]))
UserId
-> Maybe NotificationId
-> Maybe (Range 1 10000 Int32)
-> Sem
     '[Error (Tagged 'TeamNotFound ()),
       Error (Tagged 'InvalidTeamNotificationId ()), BrigAccess,
       SparAccess, NotificationSubsystem, GundeckAPIAccess, Rpc,
       ExternalAccess, FederatorAccess, BackendNotificationQueueAccess,
       BotAccess, FireAndForget, ClientStore, CodeStore, ProposalStore,
       ConversationStore, SubConversationStore, Random,
       CustomBackendStore, TeamFeatureStore, LegalHoldStore, MemberStore,
       SearchVisibilityStore, ServiceStore, TeamNotificationStore,
       TeamStore, TeamMemberStore InternalPaging,
       TeamMemberStore CassandraPaging, ListItems CassandraPaging ConvId,
       ListItems CassandraPaging (Remote ConvId),
       ListItems LegacyPaging ConvId, ListItems LegacyPaging TeamId,
       ListItems InternalPaging TeamId, Input AllTeamFeatures,
       Input (Maybe [TeamId], FeatureDefaults LegalholdConfig),
       Input (Local ()), Input Opts, Input UTCTime, Queue DeleteItem,
       Logger (Msg -> Msg), Error DynError, Input ClientState, Input Env,
       Error InvalidInput, Error InternalError, Error FederationError,
       Async, Delay, Fail, Embed IO, Error JSONResponse, Resource,
       Final IO]
     QueuedNotificationList
forall (r :: EffectRow).
(Member BrigAccess r, Member (Error (Tagged 'TeamNotFound ())) r,
 Member (Error (Tagged 'InvalidTeamNotificationId ())) r,
 Member TeamNotificationStore r) =>
UserId
-> Maybe NotificationId
-> Maybe (Range 1 10000 Int32)
-> Sem r QueuedNotificationList
getTeamNotifications

type SizeRange = Range 1 10000 Int32

-- | See also: 'Gundeck.API.Public.paginateH', but the semantics of this end-point is slightly
-- less warped.  This is a work-around because we cannot send events to all of a large team.
-- See haddocks of module "Galley.API.TeamNotifications" for details.
getTeamNotifications ::
  ( Member BrigAccess r,
    Member (ErrorS 'TeamNotFound) r,
    Member (ErrorS 'InvalidTeamNotificationId) r,
    Member TeamNotificationStore r
  ) =>
  UserId ->
  Maybe NotificationId ->
  Maybe SizeRange ->
  Sem r QueuedNotificationList
getTeamNotifications :: forall (r :: EffectRow).
(Member BrigAccess r, Member (Error (Tagged 'TeamNotFound ())) r,
 Member (Error (Tagged 'InvalidTeamNotificationId ())) r,
 Member TeamNotificationStore r) =>
UserId
-> Maybe NotificationId
-> Maybe (Range 1 10000 Int32)
-> Sem r QueuedNotificationList
getTeamNotifications UserId
uid Maybe NotificationId
since Maybe (Range 1 10000 Int32)
size = do
  Maybe NotificationId
since' <- Maybe NotificationId -> Sem r (Maybe NotificationId)
forall (r :: EffectRow).
Member (Error (Tagged 'InvalidTeamNotificationId ())) r =>
Maybe NotificationId -> Sem r (Maybe NotificationId)
checkSince Maybe NotificationId
since
  UserId
-> Maybe NotificationId
-> Range 1 10000 Int32
-> Sem r QueuedNotificationList
forall (r :: EffectRow).
(Member BrigAccess r, Member (Error (Tagged 'TeamNotFound ())) r,
 Member TeamNotificationStore r) =>
UserId
-> Maybe NotificationId
-> Range 1 10000 Int32
-> Sem r QueuedNotificationList
APITeamQueue.getTeamNotifications
    UserId
uid
    Maybe NotificationId
since'
    (Range 1 10000 Int32
-> Maybe (Range 1 10000 Int32) -> Range 1 10000 Int32
forall a. a -> Maybe a -> a
fromMaybe Range 1 10000 Int32
defaultSize Maybe (Range 1 10000 Int32)
size)
  where
    checkSince ::
      (Member (ErrorS 'InvalidTeamNotificationId) r) =>
      Maybe NotificationId ->
      Sem r (Maybe NotificationId)
    checkSince :: forall (r :: EffectRow).
Member (Error (Tagged 'InvalidTeamNotificationId ())) r =>
Maybe NotificationId -> Sem r (Maybe NotificationId)
checkSince Maybe NotificationId
Nothing = Maybe NotificationId -> Sem r (Maybe NotificationId)
forall a. a -> Sem r a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe NotificationId
forall a. Maybe a
Nothing
    checkSince (Just NotificationId
nid)
      | (UUID -> Int
UUID.version (UUID -> Int) -> (NotificationId -> UUID) -> NotificationId -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NotificationId -> UUID
forall {k} (a :: k). Id a -> UUID
toUUID) NotificationId
nid Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 =
          (Maybe NotificationId -> Sem r (Maybe NotificationId)
forall a. a -> Sem r a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe NotificationId -> Sem r (Maybe NotificationId))
-> (NotificationId -> Maybe NotificationId)
-> NotificationId
-> Sem r (Maybe NotificationId)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NotificationId -> Maybe NotificationId
forall a. a -> Maybe a
Just) NotificationId
nid
    checkSince (Just NotificationId
_) = forall {k} (e :: k) (r :: EffectRow) a.
Member (ErrorS e) r =>
Sem r a
forall (e :: GalleyError) (r :: EffectRow) a.
Member (ErrorS e) r =>
Sem r a
throwS @'InvalidTeamNotificationId

    defaultSize :: SizeRange
    defaultSize :: Range 1 10000 Int32
defaultSize = Int32 -> Range 1 10000 Int32
forall a (n :: Nat) (m :: Nat).
(Show a, KnownNat n, KnownNat m, Within a n m) =>
a -> Range n m a
unsafeRange Int32
1000