module Mensam.Server.Application.Email.Class where

import Control.Monad.Trans.Class
import Control.Monad.Trans.Compose
import Control.Monad.Trans.Elevator
import Data.Kind
import Data.Text qualified as T
import GHC.Generics
import Text.Email.Parser

type MonadEmail :: (Type -> Type) -> Constraint
class Monad m => MonadEmail m where
  sendEmail :: Email -> m SendEmailResult

instance
  ( Monad (t m)
  , MonadTrans t
  , MonadEmail m
  ) =>
  MonadEmail (Elevator t m)
  where
  sendEmail :: Email -> Elevator t m SendEmailResult
sendEmail = m SendEmailResult -> Elevator t m SendEmailResult
forall (m :: * -> *) a. Monad m => m a -> Elevator t m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m SendEmailResult -> Elevator t m SendEmailResult)
-> (Email -> m SendEmailResult)
-> Email
-> Elevator t m SendEmailResult
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Email -> m SendEmailResult
forall (m :: * -> *). MonadEmail m => Email -> m SendEmailResult
sendEmail

deriving via
  Elevator t1 ((t2 :: (Type -> Type) -> Type -> Type) m)
  instance
  {-# OVERLAPPABLE #-}
    ( Monad (t1 (t2 m))
    , MonadTrans t1
    , MonadEmail (t2 m)
    ) =>
    MonadEmail (ComposeT t1 t2 m)

type Email :: Type
data Email = MkEmail
  { Email -> EmailAddress
emailRecipient :: EmailAddress
  , Email -> Text
emailTitle :: T.Text
  , Email -> Text
emailBodyHtml :: T.Text
  }
  deriving stock (Email -> Email -> Bool
(Email -> Email -> Bool) -> (Email -> Email -> Bool) -> Eq Email
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Email -> Email -> Bool
== :: Email -> Email -> Bool
$c/= :: Email -> Email -> Bool
/= :: Email -> Email -> Bool
Eq, (forall x. Email -> Rep Email x)
-> (forall x. Rep Email x -> Email) -> Generic Email
forall x. Rep Email x -> Email
forall x. Email -> Rep Email x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Email -> Rep Email x
from :: forall x. Email -> Rep Email x
$cto :: forall x. Rep Email x -> Email
to :: forall x. Rep Email x -> Email
Generic, Eq Email
Eq Email =>
(Email -> Email -> Ordering)
-> (Email -> Email -> Bool)
-> (Email -> Email -> Bool)
-> (Email -> Email -> Bool)
-> (Email -> Email -> Bool)
-> (Email -> Email -> Email)
-> (Email -> Email -> Email)
-> Ord Email
Email -> Email -> Bool
Email -> Email -> Ordering
Email -> Email -> Email
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Email -> Email -> Ordering
compare :: Email -> Email -> Ordering
$c< :: Email -> Email -> Bool
< :: Email -> Email -> Bool
$c<= :: Email -> Email -> Bool
<= :: Email -> Email -> Bool
$c> :: Email -> Email -> Bool
> :: Email -> Email -> Bool
$c>= :: Email -> Email -> Bool
>= :: Email -> Email -> Bool
$cmax :: Email -> Email -> Email
max :: Email -> Email -> Email
$cmin :: Email -> Email -> Email
min :: Email -> Email -> Email
Ord, ReadPrec [Email]
ReadPrec Email
Int -> ReadS Email
ReadS [Email]
(Int -> ReadS Email)
-> ReadS [Email]
-> ReadPrec Email
-> ReadPrec [Email]
-> Read Email
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS Email
readsPrec :: Int -> ReadS Email
$creadList :: ReadS [Email]
readList :: ReadS [Email]
$creadPrec :: ReadPrec Email
readPrec :: ReadPrec Email
$creadListPrec :: ReadPrec [Email]
readListPrec :: ReadPrec [Email]
Read, Int -> Email -> ShowS
[Email] -> ShowS
Email -> String
(Int -> Email -> ShowS)
-> (Email -> String) -> ([Email] -> ShowS) -> Show Email
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Email -> ShowS
showsPrec :: Int -> Email -> ShowS
$cshow :: Email -> String
show :: Email -> String
$cshowList :: [Email] -> ShowS
showList :: [Email] -> ShowS
Show)

type SendEmailResult :: Type
data SendEmailResult
  = EmailSent
  | EmailFailedToSend