content: {-# LANGUAGE FlexibleInstances     #-}
  {-# LANGUAGE MultiParamTypeClasses #-}
  {-# LANGUAGE OverloadedStrings     #-}
  {-# LANGUAGE TypeFamilies          #-}
  -------------------------------------------
  -- |
  -- Module      : Web.Stripe.Invoice
  -- Copyright   : (c) David Johnson, 2014
  -- Maintainer  : code@dmj.io
  -- Stability   : experimental
  -- Portability : POSIX
  --
  -- < https:/\/\stripe.com/docs/api#invoices >
  --
  -- @
  -- {-\# LANGUAGE OverloadedStrings \#-}
  -- import Web.Stripe
  -- import Web.Stripe.Customer
  -- import Web.Stripe.Invoice
  -- import Web.Stripe.InvoiceItem
  -- import Web.Stripe.Plan
  --
  -- main :: IO ()
  -- main = do
  --   let config = StripeConfig (SecretKey "secret_key")
  --   result <- stripe config createCustomer
  --   case result of
  --     (Left stripeError) -> print stripeError
  --     (Right (Customer { customerId = cid })) ->
  --       do result <- stripe config $
  --            createPlan (PlanId "planid") (Amount 20) USD Day (PlanName "testplan")
  --          case result of
  --            (Left stripeError) -> print stripeError
  --            (Right (Plan {})) ->
  --              do result <- stripe config $
  --                   createInvoiceItem cid (Amount 100) USD
  --                 case result of
  --                   (Left stripeError)  -> print stripeError
  --                   (Right invoiceItem) ->
  --                      do result <- stripe config $ createInvoice cid
  --                         case result of
  --                           (Left  stripeError) -> print stripeError
  --                           (Right invoice)     -> print invoice
  -- @
  module Web.Stripe.Invoice
      ( -- * API
        CreateInvoice
      , createInvoice
      , GetInvoice
      , getInvoice
      , GetInvoiceLineItems
      , getInvoiceLineItems
      , GetUpcomingInvoice
      , getUpcomingInvoice
      , UpdateInvoice
      , updateInvoice
      , PayInvoice
      , payInvoice
      , GetInvoices
      , getInvoices
         -- * Types
      , ApplicationFeeId    (..)
      , Closed              (..)
      , CustomerId          (..)
      , Description         (..)
      , Discount            (..)
      , EndingBefore        (..)
      , ExpandParams        (..)
      , Forgiven            (..)
      , Invoice             (..)
      , InvoiceId           (..)
      , InvoiceLineItem     (..)
      , InvoiceLineItemId   (..)
      , InvoiceLineItemType (..)
      , Limit               (..)
      , MetaData            (..)
      , Period              (..)
      , StatementDescription(..)
      , StartingAfter       (..)
      , StripeList          (..)
      , SubscriptionId      (..)
      ) where
  
  import           Web.Stripe.StripeRequest (Method(GET, POST), StripeRequest(..),
                                             StripeReturn, StripeHasParam,
                                             toStripeParam, mkStripeRequest)
  import           Web.Stripe.Util          ((</>))
  import           Web.Stripe.Types         (ApplicationFeeId(..), Closed(..),
                                             CustomerId(..), Description(..),
                                             Discount(..), EndingBefore(..),
                                             ExpandParams(..), Forgiven(..),
                                             Invoice(..),InvoiceId(..),
                                             InvoiceLineItem(..),
                                             InvoiceLineItemId(..),
                                             InvoiceLineItemType(..),
                                             Limit(..), MetaData(..), Period(..),
                                             SubscriptionId(..), StartingAfter(..),
                                             StatementDescription(..),
                                             StripeList(..))
  import           Web.Stripe.Types.Util    (getInvoiceId)
  
  ------------------------------------------------------------------------------
  -- | The `Invoice` to be created for a `Customer`
  createInvoice
      :: CustomerId -- ^ `CustomerId` of `Customer` to `Invoice`
      -> StripeRequest CreateInvoice
  createInvoice
      customerid
                  = request
    where request = mkStripeRequest POST url params
          url     = "invoices"
          params  = toStripeParam customerid $
                    []
  
  data CreateInvoice
  type instance StripeReturn CreateInvoice = Invoice
  instance StripeHasParam CreateInvoice ApplicationFeeId
  instance StripeHasParam CreateInvoice Description
  instance StripeHasParam CreateInvoice MetaData
  instance StripeHasParam CreateInvoice StatementDescription
  instance StripeHasParam CreateInvoice SubscriptionId
  
  ------------------------------------------------------------------------------
  -- | Retrieve an `Invoice` by `InvoiceId`
  getInvoice
      :: InvoiceId -- ^ Get an `Invoice` by `InvoiceId`
      -> StripeRequest GetInvoice
  getInvoice
      invoiceid = request
    where request = mkStripeRequest GET url params
          url     = "invoices" </> getInvoiceId invoiceid
          params  = []
  
  data GetInvoice
  type instance StripeReturn GetInvoice = Invoice
  instance StripeHasParam GetInvoice ExpandParams
  
  ------------------------------------------------------------------------------
  -- | Retrieve a `StripeList` of `Invoice`s
  getInvoices
      :: StripeRequest GetInvoices
  getInvoices = request
    where request = mkStripeRequest GET url params
          url     = "invoices"
          params  = []
  
  data GetInvoices
  type instance StripeReturn GetInvoices = StripeList Invoice
  instance StripeHasParam GetInvoices ExpandParams
  instance StripeHasParam GetInvoices (EndingBefore InvoiceId)
  instance StripeHasParam GetInvoices Limit
  instance StripeHasParam GetInvoices CustomerId
  instance StripeHasParam GetInvoices (StartingAfter InvoiceId)
  
  ------------------------------------------------------------------------------
  -- | Retrieve an `InvoiceLineItem`s by `InvoiceId`
  getInvoiceLineItems
      :: InvoiceId                       -- ^ Get an `Invoice` by `InvoiceId`
      -> StripeRequest GetInvoiceLineItems
  getInvoiceLineItems
      invoiceid   = request
    where request = mkStripeRequest GET url params
          url     = "invoices" </> getInvoiceId invoiceid </> "lines"
          params  = []
  
  data GetInvoiceLineItems
  type instance StripeReturn GetInvoiceLineItems = StripeList InvoiceLineItem
  instance StripeHasParam GetInvoiceLineItems CustomerId
  instance StripeHasParam GetInvoiceLineItems (EndingBefore InvoiceLineItemId)
  instance StripeHasParam GetInvoiceLineItems Limit
  instance StripeHasParam GetInvoiceLineItems (StartingAfter InvoiceLineItemId)
  instance StripeHasParam GetInvoiceLineItems SubscriptionId
  
  ------------------------------------------------------------------------------
  -- | Retrieve an upcoming `Invoice` for a `Customer` by `CustomerId`
  getUpcomingInvoice
      :: CustomerId -- ^ The `InvoiceId` of the `Invoice` to retrieve
      -> StripeRequest GetUpcomingInvoice
  getUpcomingInvoice
      customerid = request
    where request = mkStripeRequest GET url params
          url     = "invoices" </> "upcoming"
          params  = toStripeParam customerid []
  
  data GetUpcomingInvoice
  type instance StripeReturn GetUpcomingInvoice = Invoice
  instance StripeHasParam GetUpcomingInvoice SubscriptionId
  
  ------------------------------------------------------------------------------
  -- | Update `Invoice` by `InvoiceId`
  updateInvoice
      :: InvoiceId -- ^ The `InvoiceId` of the `Invoice` to update
      -> StripeRequest UpdateInvoice
  updateInvoice
      invoiceid   = request
    where request = mkStripeRequest POST url params
          url     = "invoices" </> getInvoiceId invoiceid
          params  = []
  
  data UpdateInvoice
  type instance StripeReturn UpdateInvoice = Invoice
  instance StripeHasParam UpdateInvoice ApplicationFeeId
  instance StripeHasParam UpdateInvoice Closed
  instance StripeHasParam UpdateInvoice Description
  instance StripeHasParam UpdateInvoice Forgiven
  instance StripeHasParam UpdateInvoice MetaData
  instance StripeHasParam UpdateInvoice StatementDescription
  
  ------------------------------------------------------------------------------
  -- | Pay `Invoice` by `InvoiceId`
  payInvoice
      :: InvoiceId -- ^ The `InvoiceId` of the `Invoice` to pay
      -> StripeRequest PayInvoice
  payInvoice
      invoiceid   = request
    where request = mkStripeRequest POST url params
          url     = "invoices" </> getInvoiceId invoiceid </> "pay"
          params  = []
  
  data PayInvoice
  type instance StripeReturn PayInvoice = Invoice
  