defmodule Operately.Support.Notifications do
  import Ecto.Query, only: [from: 2]

  alias Operately.Repo
  alias Operately.People.Person
  alias Operately.Notifications.Notification

  defmacro __using__(_opts) do
    quote do
       import Operately.Support.Notifications
    end
  end

  def notifications_count do
    Repo.aggregate(Notification, :count, :id)
  end

  def notifications_count(action: action) do
    from(n in Notification,
      join: a in assoc(n, :activity),
      where: a.action == ^action
    )
    |> Repo.aggregate(:count)
  end

  def perform_job(activity_id) do
    Oban.Testing.perform_job(Operately.Activities.NotificationDispatcher, %{activity_id: activity_id}, [])
  end

  def fetch_notification(activity_id) do
    from(n in Notification, where: n.activity_id == ^activity_id) |> Repo.one()
  end

  def fetch_notifications(activity_id) do
    from(n in Notification, where: n.activity_id == ^activity_id) |> Repo.all()
  end

  def fetch_notifications(activity_id, action: action) do
    from(n in Notification,
      join: a in assoc(n, :activity),
      where: n.activity_id == ^activity_id and a.action == ^action
    )
    |> Repo.all()
  end

  def notification_message(%Person{id: id, full_name: full_name}, opts \\ []) do
    %{
      type: :doc,
      content: [
        %{
          type: :paragraph,
          content: [
            %{
              type: :mention,
              attrs: %{
                id: id,
                label: full_name
              }
            }
          ]
        }
      ]
    }
    |> then(fn msg ->
      if Keyword.get(opts, :encoded, true) do
        Jason.encode!(msg)
      else
        msg
      end
    end)
  end
end
