<commit_before>defmodule CoursePlanner.Notifier do
  @moduledoc """
  Module responsible for notifying users through e-mail with changes
  """
  use GenServer
  alias CoursePlanner.{Mailer, Mailer.UserEmail, Notification, Repo, User}
  require Logger
  import Ecto.Query

  @spec start_link :: GenServer.start_link
  def start_link do
    GenServer.start_link(__MODULE__, [], name: __MODULE__)
  end

  @spec notify_user(Notification.t) :: GenServer.cast
  def notify_user(%Notification{} = notification) do
    GenServer.cast(__MODULE__, {:send_email, notification})
  end

  @spec notify_later(Notification.t) :: GenServer.cast
  def notify_later(%Notification{} = notification) do
    GenServer.cast(__MODULE__, {:save_email, notification})
  end

  @spec notify_all(User.t) :: GenServer.cast
  def notify_all(%User{notifications: []} = _user), do: :nothing
  def notify_all(%User{} = user) do
    GenServer.cast(__MODULE__, {:notify_all, user})
  end

  @spec handle_cast({atom(), Notification.t} | atom(), any()) :: {:noreply, any()}
  def handle_cast({:send_email, notification}, state) do
    email = UserEmail.build_email(notification)
    case Mailer.deliver(email) do
      {:ok, _} ->
        {:noreply, state}
      {:error, reason} ->
        Logger.error("Email delivery failed: #{Kernel.inspect reason}")
        {:noreply, [{:error, reason, email} | state]}
    end
  end
  def handle_cast({:save_email, notification}, state) do
    changeset = Notification.changeset(notification)
    case Repo.insert(changeset) do
      {:ok, _} ->
        {:noreply, state}
      {:error, %{errors: errors, data: email}} ->
        Logger.error("Email saving failed: #{Kernel.inspect errors}")
        {:noreply, [{:error, errors, email} | state]}
    end
  end
  def handle_cast({:notify_all, user}, state) do
    email = UserEmail.build_summary(user)
    case Mailer.deliver(email) do
      {:ok, _} ->
        delete_notifications(user)
        {:noreply, state}
      {:error, reason} ->
        Logger.error("Email delivery failed: #{Kernel.inspect reason}")
        {:noreply, [{:error, reason, email} | state]}
    end
  end
  def handle_cast(_, state), do: {:noreply, state}

  defp delete_notifications(user) do
    Notification
    |> where([n], n.user_id == ^user.id)
    |> Repo.delete_all()
  end

  @doc """
  This function is used to suppress unhandled message warnings from `Swoosh.Adapters.Test` during
  unit tests
  """
  @spec handle_info(any(), any()) :: {:noreply, any()}
  def handle_info(_, state), do: {:noreply, state}
end<commit_msg>Delete only loaded notifications.<commit_after>defmodule CoursePlanner.Notifier do
  @moduledoc """
  Module responsible for notifying users through e-mail with changes
  """
  use GenServer
  alias CoursePlanner.{Mailer, Mailer.UserEmail, Notification, Repo, User}
  require Logger

  @spec start_link :: GenServer.start_link
  def start_link do
    GenServer.start_link(__MODULE__, [], name: __MODULE__)
  end

  @spec notify_user(Notification.t) :: GenServer.cast
  def notify_user(%Notification{} = notification) do
    GenServer.cast(__MODULE__, {:send_email, notification})
  end

  @spec notify_later(Notification.t) :: GenServer.cast
  def notify_later(%Notification{} = notification) do
    GenServer.cast(__MODULE__, {:save_email, notification})
  end

  @spec notify_all(User.t) :: GenServer.cast
  def notify_all(%User{notifications: []} = _user), do: :nothing
  def notify_all(%User{} = user) do
    GenServer.cast(__MODULE__, {:notify_all, user})
  end

  @spec handle_cast({atom(), Notification.t} | atom(), any()) :: {:noreply, any()}
  def handle_cast({:send_email, notification}, state) do
    email = UserEmail.build_email(notification)
    case Mailer.deliver(email) do
      {:ok, _} ->
        {:noreply, state}
      {:error, reason} ->
        Logger.error("Email delivery failed: #{Kernel.inspect reason}")
        {:noreply, [{:error, reason, email} | state]}
    end
  end
  def handle_cast({:save_email, notification}, state) do
    changeset = Notification.changeset(notification)
    case Repo.insert(changeset) do
      {:ok, _} ->
        {:noreply, state}
      {:error, %{errors: errors, data: email}} ->
        Logger.error("Email saving failed: #{Kernel.inspect errors}")
        {:noreply, [{:error, errors, email} | state]}
    end
  end
  def handle_cast({:notify_all, user}, state) do
    email = UserEmail.build_summary(user)
    case Mailer.deliver(email) do
      {:ok, _} ->
        delete_notifications(user)
        {:noreply, state}
      {:error, reason} ->
        Logger.error("Email delivery failed: #{Kernel.inspect reason}")
        {:noreply, [{:error, reason, email} | state]}
    end
  end
  def handle_cast(_, state), do: {:noreply, state}

  defp delete_notifications(user) do
    user.notifications
    |> Enum.each(&Repo.delete/1)
  end

  @doc """
  This function is used to suppress unhandled message warnings from `Swoosh.Adapters.Test` during
  unit tests
  """
  @spec handle_info(any(), any()) :: {:noreply, any()}
  def handle_info(_, state), do: {:noreply, state}
end
{'fraction_non_alphanumeric': 0.1392429888213375, 'fraction_numerical': 0.00019611688566385565, 'mean_word_length': 3.7574626865671643, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6790431', 'n_tokens_mistral': 1661, 'n_tokens_neox': 1580, 'n_words': 411}