lib/requests.ex

defmodule Requests do
  alias Requests.Customers.Create, as: CreateCustomer
  alias Requests.Customers.Update, as: UpdateCustomer

  alias Requests.Instruments.{
    CreateBankAccount,
    CreateToken,
    UpdateBankAccount,
    UpdateCard
  }

  alias Requests.Payments.{
    CapturePayment,
    CardPayout,
    BankPayout,
    Payment
  }

  def build(%{type: "bank_payout"} = params) do
    with %BankPayout{} = request <- BankPayout.build(params) do
      {:ok, request}
    end
  end

  def build(%{type: "card_payout"} = params) do
    with %CardPayout{} = request <- CardPayout.build(params) do
      {:ok, request}
    end
  end

  def build(%{type: "payment_payout"} = params) do
    with %Payment{} = payment <- Payment.build(params) do
      {:ok, payment}
    end
  end

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

  def create(%{type: "bank_account"} = params) do
    with %CreateBankAccount{} = bank_account <- CreateBankAccount.build(params) do
      {:ok, bank_account}
    end
  end

  def create(%{type: "token"} = params) do
    with %CreateToken{} = token <- CreateToken.build(params) do
      {:ok, token}
    end
  end

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

  def update(%{type: "bank_account"} = params) do
    with %UpdateBankAccount{} = bank_account <- UpdateBankAccount.build(params) do
      {:ok, bank_account}
    end
  end

  def update(%{type: "card"} = params) do
    with %UpdateCard{} = card <- UpdateCard.build(params) do
      {:ok, card}
    end
  end

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

  def build("capture_payment", %{id: id} = params) do
    with %CapturePayment{} = payment <- CapturePayment.build(params) do
      {payment, "payments/#{id}/captures"}
    end
  end

  def build("void_payment", %{id: id} = params) do
    with %Requests.VoidPayment{} = payment <- Requests.VoidPayment.build(params) do
      {payment, "payments/#{id}/voids"}
    end
  end

  def build("create_customer", params) do
    with %CreateCustomer{} = customer <- CreateCustomer.build(params) do
      {:ok, customer}
    end
  end

  def build("update_customer", params) do
    with %UpdateCustomer{} = customer <- UpdateCustomer.build(params) do
      {:ok, customer}
    end
  end

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

  def build("payment_list", "", _opts), do: {:error, "payment list must have a reference"}

  def build("payment_list", reference, %{limit: limit, skip: skip}) when is_binary(reference) do
    {:ok, "limit=#{limit}&skip=#{skip}&reference=#{reference}"}
  end

  def build("payment_list", reference, %{limit: limit}) when is_binary(reference) do
    {:ok, "limit=#{limit}&skip=0&reference=#{reference}"}
  end

  def build("payment_list", reference, %{skip: skip}) when is_binary(reference) do
    {:ok, "limit=10&skip=#{skip}&reference=#{reference}"}
  end

  def build("payment_list", reference, %{}) when is_binary(reference) do
    {:ok, "limit=10&skip=0&reference=#{reference}"}
  end

  def build("payment_list", _reference, _opts), do: {:error, "payment list must have a reference"}
end