{-# LANGUAGE DataKinds                  #-}
{-# LANGUAGE DeriveFoldable             #-}
{-# LANGUAGE DeriveFunctor              #-}
{-# LANGUAGE DeriveGeneric              #-}
{-# LANGUAGE DeriveTraversable          #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE NoImplicitPrelude          #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE QuasiQuotes                #-}
{-# LANGUAGE ScopedTypeVariables        #-}
{-# LANGUAGE TemplateHaskell            #-}
{-# LANGUAGE TypeOperators              #-}
{-# LANGUAGE TypeSynonymInstances       #-}
module Query.Role where

import           Data.Aeson
import           Data.Aeson.Types
import           Data.Maybe
import           Data.Profunctor.Product
import           Data.Profunctor.Product.Default
import           Data.Profunctor.Product.TH           (makeAdaptorAndInstance)
import           Data.Text                            (Text)
import qualified Data.Text.Encoding                   as TE
import           Data.UUID                            (UUID, fromASCIIBytes,
                                                       toASCIIBytes)
import qualified Data.UUID                            as UUID
import qualified Database.PostgreSQL.Simple           as PGS
import           Database.PostgreSQL.Simple.FromField (Conversion,
                                                       FromField (..),
                                                       ResultError (..),
                                                       returnError)
import qualified GHC.Generics                         as GHC
import qualified Hasql.Decoders                       as HD
import qualified Hasql.Encoders                       as HE
import           NeatInterpolation
import           Opaleye
import           Protolude                            hiding (Generic, optional,
                                                       (&))

import           Types.Domain
import           Types.Domain.Status
import           Utils

--------------------------------------------------------------------------------
type RoleTableR = RolePoly
    (Column PGUuid)
    (Column PGText)

--------------------------------------------------------------------------------
type RoleTableW = RolePoly
    (Maybe (Column PGUuid))
    (Column PGText)

--------------------------------------------------------------------------------
$(makeAdaptorAndInstance "pRole" ''RolePoly)
roleTable :: Table RoleTableW RoleTableR
roleTable = Table "roles" (pRole
   Role {
     roleId = (optional "id"),
     roleName = (required "name")
   }
 )

instance Default Constant UUID (Maybe (Column PGUuid)) where
  def = Constant ((Just).pgUUID)

--------------------------------------------------------------------------------
getRoles :: PGS.Connection -> IO [Role]
getRoles conn = do
  runQuery conn $ queryTable roleTable

--------------------------------------------------------------------------------
insertRole :: PGS.Connection -> Role -> IO (Maybe Role)
insertRole conn role = do
  rows <- runInsertManyReturning conn roleTable [constant role] (\x -> x) :: IO [Role]
  pure $ listToMaybe rows
