lib/checkout_sdk.ex

defmodule CheckoutSdk do
  @moduledoc """
  Documentation for `CheckoutSdk`.
  """

  @doc """
    https://api-reference.checkout.com/#operation/createAnInstrument

    ## Examples

      iex> CheckoutSdk.create_instrument(%{type: "token", token: "tok_hblh3ceyhygenhqmypki3kiyxu"})
      {:ok, %Responses.Instruments.CreateCard{}}

      iex> CheckoutSdk.create_instrument(%{type: "bank_account", currency: "USD", country: "US", bank_code: "something here", account_type:  "cash"})
      {:ok, %Responses.Instruments.CreateBankAccount{}}
  """
  def create_instrument(params) do
    with {:ok, request} <- Requests.create(params),
         {:ok, response} <- Client.post(request, "instruments"),
         instrument when is_map(instrument) <- Responses.build(response, "create_instrument") do
      {:ok, instrument}
    end
  end

  @doc """
    https://api-reference.checkout.com/#operation/getInstrumentDetails

    ## Examples

      iex> CheckoutSdk.get_instrument_details("src_yvqm6xgmiiouje5ysca25qkc5a")
      {:ok, %Responses.Instruments.CardDetails{}}

      iex> CheckoutSdk.get_instrument_details("src_yf7cb7y3cvmehg5frazq32sdyq")
      {:ok, %Responses.Instruments.BankAccountDetails{}}

  """
  def get_instrument_details(id) do
    with {:ok, response} <- Client.get(%{id: id}, "instruments"),
         instrument when is_map(instrument) <- Responses.build(response, "instrument_details") do
      {:ok, instrument}
    end
  end

  @doc """
    https://api-reference.checkout.com/#tag/Instruments/paths/~1instruments~1%7Bid%7D/patch

    ## Examples

      iex> CheckoutSdk.update_instrument(%{type: "card", id: "src_blvzu7xtwqcunjhs7k3smgbgii", name: "Tiberous Kirk"})
      {:ok, %Responses.Instruments.Update{}}

      iex> CheckoutSdk.update_instrument(%{type: "bank_account", id: "src_bjmpkcgyfmie3drnxrtuaw6qsa", bank_code: "something"})
      {:ok, %Responses.Instruments.Update{}}

  """
  def update_instrument(params) do
    with {:ok, body} <- Requests.update(params),
         {:ok, response} <- Client.update(body, "instruments"),
         instrument when is_map(instrument) <- Responses.build(response, "update_instrument") do
      {:ok, instrument}
    end
  end

  @doc """
    https://api-reference.checkout.com/#tag/Instruments/paths/~1instruments~1%7Bid%7D/delete

    ## Examples

      iex> CheckoutSdk.delete_instrument("src_blvzu7xtwqcunjhs7k3smgbgii")
      {:ok, "src_gwvz3x2q7zcubduwa73nuwoyoi was deleted sucessfully"}

  """
  def delete_instrument(id) do
    with {:ok, response} <- Client.delete(%{id: id}, "instruments") do
      {:ok, response}
    end
  end

  @doc """
    https://api-reference.checkout.com/#operation/createCustomer

    ## Examples

      iex> CheckoutSdk.create_customer(%{email: "tiberious_kirk1@gmail.com", name: "Tiberious Kirk"})
      {:ok, %{id: "cus_sobjzu2jtgvurgnslxtjfdoh6u"}}

  """
  def create_customer(params) do
    with {:ok, body} <- Requests.build("create_customer", params),
         {:ok, response} <- Client.post(body, "customers"),
         customer when is_map(customer) <- Responses.build(response, "create_customer") do
      {:ok, customer}
    end
  end

  @doc """
    https://api-reference.checkout.com/#operation/getCustomerDetails

    ## Examples

      iex> CheckoutSdk.get_customer_details("cus_zmcfxfdhec2udpilxpjyb5daue")
      {:ok, %Customers.Customer{}}

  """
  def get_customer_details(id) when is_binary(id) do
    with {:ok, response} <- Client.get(%{id: id}, "customers") do
      {:ok, Responses.build(response, "customer_details")}
    end
  end

  def get_customer_details(_), do: {:error, "must have valid id"}

  @doc """
    https://api-reference.checkout.com/#tag/Customers/paths/~1customers~1%7Bidentifier%7D/patch

    ## Examples

      iex> CheckoutSdk.update_customer(%{id: "cus_zmcfxfdhec2udpilxpjyb5daue", name: "Iwatski Yuko"})
      {:ok, "update successful"}

  """
  def update_customer(params) do
    with {:ok, body} <- Requests.build("update_customer", params),
         {:ok, _response} <- Client.update(body, "customers") do
      {:ok, "Customer updated successfully"}
    end
  end

  @doc """
    https://api-reference.checkout.com/#tag/Customers/paths/~1customers~1%7Bidentifier%7D/delete

    ## Examples

      iex> CheckoutSdk.delete_customer("cus_zmcfxfdhec2udpilxpjyb5daue")
      {:ok, "cus_dcpwo7ypgfzefcxsvukpl235d4 was deleted sucessfully"}

  """
  def delete_customer(id) when is_binary(id) do
    Client.delete(%{id: id}, "customers")
  end

  def delete_customer(_), do: {:error, "must have an id"}

  @doc """
    https://api-reference.checkout.com/#operation/requestAPaymentOrPayout

    ## Examples
      iex> payment_params = %{
      ...>         type: "payment_payout",
      ...>         source: %{
      ...>           type: "id",
      ...>           id: "src_lni6s3c2ra4ufcgnyr7vbidz2u"
      ...>         },
      ...>         capture: false,
      ...>         currency: "USD",
      ...>         amount: 100,
      ...>         processing_channel_id: "pc_iiacs2ehunsu3d6inimxkvhlia"
      ...>       }
      iex> CheckoutSdk.request_payment_or_payout(payment_params)
      {:ok, %Responses.Payment{}}

      CardPayout and BankPayout Requests are not working need to be configured with Checkout.com

  """
  def request_payment_or_payout(params) do
    with {:ok, body} <- Requests.build(params),
         {:ok, response} <- Client.post(body, "payments"),
         payout when is_map(payout) <- Responses.build(response, "payments") do
      {:ok, payout}
    end
  end

  @doc """
    https://api-reference.checkout.com/#operation/captureAPayment

    ## Examples

      iex> CheckoutSdk.capture_payment(%{id: "pay_qzf4qcix7ezurgmdwai5w65oy4", amount: 100, reference: "reference"})
      {:ok, %Responses.PaymentCapture{}}

  """
  def capture_payment(params) do
    with {body, url} when is_map(body) <- Requests.build("capture_payment", params),
         {:ok, response} <- Client.post(body, url) do
      {:ok, Responses.build(response, "capture_payment")}
    end
  end

  @doc """
   https://api-reference.checkout.com/#tag/Payments/paths/~1payments/get

    ## Examples

      iex> CheckoutSdk.get_payment_list("pay_qzf4qcix7ezurgmdwai5w65oy4")

  """
  def get_payment_list(reference, opts \\ %{})

  def get_payment_list(reference, opts) when is_binary(reference) do
    with {:ok, url_query} <- Requests.build("payment_list", reference, opts),
         {:ok, response} <- Client.get(url_query, "payments"),
         payment_list when is_map(payment_list) <- Responses.build(response, "payment_list") do
      {:ok, payment_list}
    end
  end

  def get_payment_list(_, _), do: {:error, "invalid params"}

  @doc """
   https://api-reference.checkout.com/#operation/getPaymentDetails

    ## Examples

      iex> CheckoutSdk.get_payment_details("pay_dw4eiq6hfuhulhaagvvd7ytnnq")
      {:ok, "details"}

  """
  def get_payment_details(payment_id) when is_binary(payment_id) do
    with {:ok, response} <- Client.get(%{id: payment_id}, "payments") do
      {:ok, Responses.build(response, "payments")}
    end
  end

  def get_payment_details(_), do: {:error, "must have valid id"}

  @doc """
    https://api-reference.checkout.com/#operation/voidAPayment

    ## Examples

      iex> CheckoutSdk.void_payment(%{id: "pay_dw4eiq6hfuhulhaagvvd7ytnnq"})
      {:ok, "voided_payment"}

  """
  def void_payment(params) do
    with {body, url} when is_map(body) <- Requests.build("void_payment", params),
         {:ok, response} <- Client.post(body, url) do
      {:ok, response}
    end
  end
end