-- SPDX-FileCopyrightText: 2022-2024 Gregor Kleen <gregor.kleen@ifi.lmu.de>, Steffen Jost <s.jost@fraport.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later

-- also see Utils.DB

module Utils.Persist
  ( fromPersistValueError
  , fromPersistValueErrorSql
  , (~=.), (~~.)
  ) where

import ClassyPrelude

import Database.Persist
import Database.Persist.Sql
import Data.Proxy
import Type.Reflection (typeRep)


fromPersistValueError :: Text -- ^ Haskell type
                      -> Text -- ^ Database type
                      -> PersistValue -- ^ Incorrect value
                      -> Text -- ^ Error Message
fromPersistValueError hType dbType received = mconcat
  [ "Failed to parse Haskell type `"
  , hType
  , "`; expected "
  , dbType
  , " from database, but received: "
  , tshow received
  , "."
  ]

fromPersistValueErrorSql :: forall p a.
                            ( PersistFieldSql a
                            , Typeable a
                            )
                         => p a
                         -> PersistValue
                         -> Text
fromPersistValueErrorSql _ = fromPersistValueError (tshow $ typeRep @a) (tshow $ sqlType (Proxy @a))


infix 4 ~=.
-- | is equal or Nothing, do not confuse with Database.Esqueleto.Utils(~=.) which does the same for proper Esqueleto queries
(~=.) :: PersistField a =>  EntityField v (Maybe a) -> a -> [Filter v]
(~=.) f v         = [f ==. Nothing] ||. [f ==. Just v]

infix 4 ~~.
-- | maybe is equal or Nothing,
(~~.) :: PersistField a =>  EntityField v (Maybe a) -> Maybe a -> [Filter v]
(~~.) f Nothing   = [f ==. Nothing]
(~~.) f (Just v)  = [f ==. Nothing] ||. [f ==. Just v]
