defmodule Microwaveprop.RepoListener do
  @moduledoc """
  Listens for PostgreSQL NOTIFY events on enrichment status changes
  and Oban job state changes, broadcasting via PubSub.
  Replaces polling with event-driven updates.
  """

  use GenServer

  require Logger

  @channels ["contact_status_changed", "oban_job_changed"]

  def start_link(opts \\ []) do
    GenServer.start_link(__MODULE__, opts, name: __MODULE__)
  end

  @impl true
  def init(_opts) do
    config = Microwaveprop.Repo.config()

    {:ok, pid} =
      Postgrex.Notifications.start_link(
        hostname: config[:hostname] || "localhost",
        port: config[:port] || 5432,
        username: config[:username],
        password: config[:password],
        database: config[:database]
      )

    for channel <- @channels do
      Postgrex.Notifications.listen!(pid, channel)
    end

    Logger.info("RepoListener: listening on #{Enum.join(@channels, ", ")}")
    {:ok, %{pid: pid}}
  end

  @impl true
  def handle_info({:notification, _pid, _ref, "contact_status_changed", payload}, state) do
    case Jason.decode(payload) do
      {:ok, data} ->
        Phoenix.PubSub.broadcast(
          Microwaveprop.PubSub,
          "db:contact_status",
          {:contact_status_changed, data}
        )

      _ ->
        :ok
    end

    {:noreply, state}
  end

  def handle_info({:notification, _pid, _ref, "oban_job_changed", payload}, state) do
    case Jason.decode(payload) do
      {:ok, data} ->
        Phoenix.PubSub.broadcast(
          Microwaveprop.PubSub,
          "db:oban_jobs",
          {:oban_job_changed, data}
        )

      _ ->
        :ok
    end

    {:noreply, state}
  end

  def handle_info(_msg, state), do: {:noreply, state}
end
