lib/step_flow/models/roles/roles.ex

defmodule StepFlow.Roles do
  @moduledoc """
  The Roles context.
  """

  require Logger

  import Ecto.Query, warn: false
  alias StepFlow.Repo

  alias StepFlow.Roles.Role

  @doc """
  Returns the list of roles.

  ## Examples

      iex> list_roles()
      [%Role{}, ...]

  """
  def list_roles(params \\ %{}) do
    page =
      Map.get(params, "page", 0)
      |> StepFlow.Integer.force()

    size =
      Map.get(params, "size", 10)
      |> StepFlow.Integer.force()

    offset = page * size

    query = from(role in Role)

    total_query = from(item in query, select: count(item.id))

    total =
      Repo.all(total_query)
      |> List.first()

    query =
      from(
        role in query,
        order_by: [asc: :name],
        offset: ^offset,
        limit: ^size
      )

    roles = Repo.all(query)

    %{
      data: roles,
      total: total,
      page: page,
      size: size
    }
  end

  @doc """
  Creates a role.

  ## Examples

      iex> create_role(%{field: value})
      {:ok, %Role{}}

      iex> create_role(%{field: bad_value})
      {:error, %Ecto.Changeset{}}

  """
  def create_role(attrs \\ %{}) do
    %Role{}
    |> Role.changeset(attrs)
    |> Repo.insert()
  end

  @doc """
  Gets a single role.

  Raises `Ecto.NoResultsError` if the Role does not exist.

  ## Examples

      iex> get_role!(123)
      %Role{}

      iex> get_role!(456)
      ** (Ecto.NoResultsError)

  """
  def get_role!(id), do: Repo.get!(Role, id)

  @doc """
  Gets a single role.

  ## Examples

      iex> get_role(123)
      %Role{}

      iex> get_role(456)
      nil

  """
  def get_role(id), do: Repo.get(Role, id)

  @doc """
  Gets a several roles.

  ## Examples

      iex> get_roles(["toto", "tata"])
      [%Role{}, %Role{}]

  """
  def get_roles(names, result \\ [])

  def get_roles([%{"name" => name, "rights" => _rights} = _role | roles], result) do
    role = get_by(%{"name" => name})
    get_roles(roles, [role | result])
  end

  def get_roles([name | names], result) do
    role = get_by(%{"name" => name})
    get_roles(names, [role | result])
  end

  def get_roles([], result), do: result

  @doc """
  Gets a single role by name

  ## Examples

      iex> get_by!(toto)
      %Role{}

      iex> get_by!(tata)
      ** (Ecto.NoResultsError)

  """
  def get_by!(%{"name" => name}) do
    Repo.get_by!(Role, name: name)
  end

  @doc """
  Gets a single role by name

  ## Examples

      iex> get_by(toto)
      %Role{}

      iex> get_by(tata)
      nil

  """
  def get_by(%{"name" => name}) do
    Repo.get_by(Role, name: name)
  end

  @doc """
  Updates a role.

  ## Examples

      iex> update_role(role, %{field: new_value})
      {:ok, %Job{}}

      iex> update_role(role, %{field: bad_value})
      {:error, %Ecto.Changeset{}}

  """
  def update_role(%Role{} = role, attrs) do
    role
    |> Role.changeset(attrs)
    |> Repo.update()
  end

  @doc """
  Returns an `%Ecto.Changeset{}` for tracking role changes.

  ## Examples

      iex> change_role(role)
      %Ecto.Changeset{source: %Role{}}

  """
  def change_role(%Role{} = role) do
    Role.changeset(role, %{})
  end

  @doc """
  Deletes a Role.

  ## Examples

      iex> delete_role(role)
      {:ok, %Role{}}

      iex> delete_role(role)
      {:error, %Ecto.Changeset{}}

  """
  def delete_role(%Role{} = role) do
    if role.is_unused == true do
      Repo.delete(role)
    else
      {:error, role}
    end
  end
end