{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes        #-}
module Mollie.API.Payments
    ( paymentsPath
    , newPayment
    , newRecurringPayment
    , createPayment
    , getPayment
    , getPayments
    , newRefund
    , createPaymentRefund
    , getPaymentRefund
    , cancelPaymentRefund
    , getPaymentRefunds
    
    , PaymentStatus (..)
    , PaymentMethod (..)
    , RecurringType (..)
    , NewPayment (..)
    , Mode (..)
    , PaymentLinks (..)
    , Payment (..)
    , ListLinks (..)
    , List (..)
    , NewRefund (..)
    , RefundStatus (..)
    , Refund (..)
    , ResponseError (..)
    ) where
import           Data.Monoid
import qualified Data.Text           as Text
import           Mollie.API.Internal
import           Mollie.API.Refunds
import           Mollie.API.Types
import qualified Network.HTTP.Types  as HTTP
paymentsPath :: Text.Text
paymentsPath = "payments"
newPayment :: Double 
           -> Text.Text 
           -> Text.Text 
           -> NewPayment
newPayment amount description redirectUrl = (newRecurringPayment amount description)
    { newPayment_redirectUrl       = Just redirectUrl
    , newPayment_recurringType     = Nothing
    }
newRecurringPayment :: Double 
                    -> Text.Text 
                    -> NewPayment
newRecurringPayment amount description = NewPayment
    { newPayment_amount            = amount
    , newPayment_description       = description
    , newPayment_redirectUrl       = Nothing
    , newPayment_webhookUrl        = Nothing
    , newPayment_method            = Nothing
    , newPayment_metadata          = Nothing
    , newPayment_locale            = Nothing
    , newPayment_recurringType     = Just Recurring
    , newPayment_customerId        = Nothing
    , newPayment_issuer            = Nothing
    , newPayment_billingAddress    = Nothing
    , newPayment_billingCity       = Nothing
    , newPayment_billingRegion     = Nothing
    , newPayment_billingPostal     = Nothing
    , newPayment_billingCountry    = Nothing
    , newPayment_shippingAddress   = Nothing
    , newPayment_shippingCity      = Nothing
    , newPayment_shippingRegion    = Nothing
    , newPayment_shippingPostal    = Nothing
    , newPayment_shippingCountry   = Nothing
    , newPayment_billingEmail      = Nothing
    , newPayment_dueDate           = Nothing
    , newPayment_consumerName      = Nothing
    , newPayment_consumerAccount   = Nothing
    , newPayment_customerReference = Nothing
    }
createPayment :: NewPayment -> Mollie (Either ResponseError Payment)
createPayment newPayment = do
    result <- send HTTP.methodPost path newPayment
    return $ decodeResult result
    where
        path = paymentsPath
getPayment :: Text.Text 
           -> Mollie (Either ResponseError Payment)
getPayment paymentId = get path
    where
        path = Text.intercalate "/" [paymentsPath, paymentId]
getPayments :: Int 
            -> Int 
            -> Mollie (Either ResponseError (List Payment))
getPayments offset count = get path
    where
        path = paymentsPath <> query
        query = "?offset=" <> showT offset <> "&count=" <> showT count
newRefund :: NewRefund
newRefund = NewRefund
    { newRefund_amount      = Nothing
    , newRefund_description = Nothing
    }
createPaymentRefund :: Text.Text 
                    -> NewRefund
                    -> Mollie (Either ResponseError Refund)
createPaymentRefund paymentId newRefund = do
    result <- send HTTP.methodPost path newRefund
    return $ decodeResult result
    where
        path = Text.intercalate "/" [paymentsPath, paymentId, refundsPath]
getPaymentRefund :: Text.Text 
                 -> Text.Text 
                 -> Mollie (Either ResponseError Refund)
getPaymentRefund paymentId refundId = get path
    where
        path = Text.intercalate "/" [paymentsPath, paymentId, refundsPath, refundId]
cancelPaymentRefund :: Text.Text 
                    -> Text.Text 
                    -> Mollie (Maybe ResponseError)
cancelPaymentRefund paymentId refundId = do
    result <- delete path
    return $ ignoreResult result
    where
        path = Text.intercalate "/" [paymentsPath, paymentId, refundsPath, refundId]
getPaymentRefunds :: Text.Text 
                  -> Int 
                  -> Int 
                  -> Mollie (Either ResponseError (List Refund))
getPaymentRefunds paymentId offset count = get path
    where
        path = (Text.intercalate "/" [paymentsPath, paymentId, refundsPath]) <> query
        query = "?offset=" <> showT offset <> "&count=" <> showT count