defmodule Prymn.Apps do
  @moduledoc """
  The Apps context.
  """

  import Ecto.Query, warn: false
  alias Prymn.Repo
  alias Prymn.Apps.App

  @doc """
  Returns the list of apps.

  ## Examples

      iex> list_apps()
      [%App{}, ...]

  """
  def list_apps do
    Repo.all(App)
    |> Repo.preload(:server)
  end

  @doc """
  Gets a single app.

  Raises `Ecto.NoResultsError` if the App does not exist.
  """
  def get_app!(id), do: Repo.get!(App, id)

  @doc """
  Creates an app and prepares it for deployment.
  """
  def create_app(%Prymn.Servers.Server{} = server, attrs \\ %{}) do
    # TODO: Any app..
    server
    |> Ecto.build_assoc(:apps)
    |> App.change_wordpress(attrs)
    |> Repo.insert()
    |> case do
      {:ok, %App{} = app} ->
        %{app_id: app.id}
        |> Prymn.Worker.new()
        |> Oban.insert()

        app

      {:error, changeset} ->
        changeset
    end
  end

  @doc """
  Updates a app.

  ## Examples

      iex> update_app(app, %{field: new_value})
      {:ok, %App{}}

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

  """
  def update_app(%App{} = app, attrs) do
    app
    |> App.changeset(attrs)
    |> Repo.update()
  end

  @doc """
  Deletes a app.

  ## Examples

      iex> delete_app(app)
      {:ok, %App{}}

      iex> delete_app(app)
      {:error, %Ecto.Changeset{}}

  """
  def delete_app(%App{} = app) do
    Repo.delete(app)
  end

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

  ## Examples

      iex> change_app(app)
      %Ecto.Changeset{data: %App{}}

  """
  def change_app(%App{} = app, attrs \\ %{}) do
    App.changeset(app, attrs)
  end
end