defmodule Forum.DB do
  @moduledoc """
  Thin wrappers around `Postgrex.query/3`. No ORM, just SQL.
  The `Forum.DB` name was registered when Postgrex started in `Application`.
  """

  def query(sql, params \\ []) do
    Postgrex.query(__MODULE__, sql, params)
  end

  def query!(sql, params \\ []) do
    Postgrex.query!(__MODULE__, sql, params)
  end

  def list_messages(opts \\ []) do
    limit = Keyword.get(opts, :limit, 50)

    %Postgrex.Result{rows: rows, columns: cols} =
      query!("SELECT id, text, inserted_at FROM messages ORDER BY id DESC LIMIT $1", [limit])

    rows_to_maps(rows, cols)
  end

  def insert_message(text) when is_binary(text) do
    %Postgrex.Result{rows: [row], columns: cols} =
      query!(
        "INSERT INTO messages (text) VALUES ($1) RETURNING id, text, inserted_at",
        [text]
      )

    [map] = rows_to_maps([row], cols)
    map
  end

  # Postgrex returns rows as lists of values + a separate list of column names.
  # Zip them into maps so JSON encoding is straightforward.
  defp rows_to_maps(rows, cols) do
    Enum.map(rows, fn row ->
      cols
      |> Enum.zip(row)
      |> Map.new()
    end)
  end
end
