-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2022 Wire Swiss GmbH <opensource@wire.com>
--
-- This program is free software: you can redistribute it and/or modify it under
-- the terms of the GNU Affero General Public License as published by the Free
-- Software Foundation, either version 3 of the License, or (at your option) any
-- later version.
--
-- This program is distributed in the hope that it will be useful, but WITHOUT
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-- details.
--
-- You should have received a copy of the GNU Affero General Public License along
-- with this program. If not, see <https://www.gnu.org/licenses/>.

module Data.LegalHold where

import Cassandra.CQL
import Control.Lens ((?~))
import Data.Aeson hiding (constructorTagModifier)
import Data.OpenApi qualified as S
import Data.Schema
import Imports
import Test.QuickCheck

data UserLegalHoldStatus
  = -- | consent is given, but no device creation request has come in yet.
    UserLegalHoldDisabled
  | -- | device creation request has come in, waiting for 2nd round of ok from user before creating client device
    UserLegalHoldPending
  | -- | lh client ok'ed, requested, and created.
    UserLegalHoldEnabled
  | -- | no consent given (not even implicit)
    UserLegalHoldNoConsent
  deriving stock (Show, Eq, Ord, Bounded, Enum, Generic)
  deriving (FromJSON, ToJSON, S.ToSchema) via Schema UserLegalHoldStatus

instance ToSchema UserLegalHoldStatus where
  schema =
    (S.schema . description ?~ desc) $
      enum @Text $
        element "enabled" UserLegalHoldEnabled
          <> element "pending" UserLegalHoldPending
          <> element "disabled" UserLegalHoldDisabled
          <> element "no_consent" UserLegalHoldNoConsent
    where
      desc =
        "states whether a user is under legal hold, "
          <> "or whether legal hold is pending approval."

defUserLegalHoldStatus :: UserLegalHoldStatus
defUserLegalHoldStatus = UserLegalHoldNoConsent

instance Cql UserLegalHoldStatus where
  ctype = Tagged IntColumn

  fromCql (CqlInt n) = case n of
    0 -> pure UserLegalHoldDisabled
    1 -> pure UserLegalHoldPending
    2 -> pure UserLegalHoldEnabled
    3 -> pure UserLegalHoldNoConsent
    _ -> Left "fromCql: Invalid UserLegalHoldStatus"
  fromCql _ = Left "fromCql: UserLegalHoldStatus: CqlInt expected"

  toCql UserLegalHoldDisabled = CqlInt 0
  toCql UserLegalHoldPending = CqlInt 1
  toCql UserLegalHoldEnabled = CqlInt 2
  toCql UserLegalHoldNoConsent = CqlInt 3

instance Arbitrary UserLegalHoldStatus where
  arbitrary = elements [minBound ..]
