lib/query/flow_runner.ex

defmodule SurrealEx.Query.QueryFlowRunner do

  def run(module, conn_module, args) do
    optional_filters(module, args)
    |> flow_optional_before(module)
    |> flow_query(module, conn_module)
  end
  def run(module, conn_module, args, token) do
    optional_filters(module, args)
    |> flow_optional_before(module)
    |> flow_query(module, conn_module, token)
  end

  defp flow_optional_before({:ok, args}, module), do: optional_before(module, args)
  defp flow_optional_before(err, _module), do: err

  defp flow_query({:ok, query_args}, module, conn_module) do
    prepare_query(module, query_args)
    |> exe_query(conn_module)
    |> optional_after(module)
  end
  defp flow_query(err, _module, _conn_module), do: err
  defp flow_query({:ok, query_args}, module, conn_module, token) do
    prepare_query(module, query_args)
    |> exe_query(conn_module, token)
    |> optional_after(module)
  end
  defp flow_query(err, _module, _conn_module, _token), do: err


  defp optional_filters(module, args) do
    if Kernel.function_exported?(module, :filters, 1) do
      filters = apply(module, :filters, [args])
      SurrealEx.ArgsChecker.apply(args, filters)
    else
      {:ok, args}
    end
  end

  defp optional_before(module, args) do
    if Kernel.function_exported?(module, :before, 1) do
      apply(module, :before, [args])
    else
      {:ok, args}
    end
  end

  defp prepare_query(module, query_args) do
    apply(module, :query, [query_args])
  end

  defp exe_query(query, conn_module) when is_bitstring(query) do
    apply(conn_module, :sql, [query])
  end
  defp exe_query(_query, _conn_module) do
    SurrealEx.Exception.query_should_be_string()
  end
  defp exe_query(query, conn_module, token) when is_bitstring(query) and is_bitstring(token) do
    apply(conn_module, :sql, [query, token])
  end
  defp exe_query(_query, _conn_module, _token) do
    SurrealEx.Exception.query_should_be_string()
  end

  defp optional_after({:ok, response}, module) do
    if Kernel.function_exported?(module, :ok, 1) do
      apply(module, :ok, [response])
    else
      {:ok, response}
    end
  end
  defp optional_after({:error, response}, module) do
    if Kernel.function_exported?(module, :error, 1) do
      apply(module, :error, [response])
    else
      {:error, response}
    end
  end



end