defmodule WhoNeedHelp.PushTest do
  use ExUnit.Case, async: false

  alias WhoNeedHelp.Push
  alias WhoNeedHelp.Push.HTTPAdapter

  defmodule RecordingAdapter do
    @behaviour Push

    @impl true
    def deliver(notification, opts) do
      send(Keyword.fetch!(opts, :test_pid), {:delivered, notification, opts})
      {:ok, %{id: "recorded", duplicate: false}}
    end
  end

  setup do
    previous = Application.get_env(:who_need_help, :push_adapter)
    Application.delete_env(:who_need_help, :push_adapter)

    on_exit(fn ->
      case previous do
        nil -> Application.delete_env(:who_need_help, :push_adapter)
        adapter -> Application.put_env(:who_need_help, :push_adapter, adapter)
      end
    end)
  end

  test "the unconfigured product boundary is disabled" do
    assert Push.deliver(notification()) == {:error, :disabled}
  end

  test "invalid notifications fail before invoking an adapter" do
    assert Push.deliver(
             Map.delete(notification(), :idempotency_key),
             adapter: RecordingAdapter,
             test_pid: self()
           ) == {:error, {:invalid_notification, :idempotency_key}}

    refute_received {:delivered, _notification, _opts}
  end

  test "a configured adapter receives validated data without the adapter option" do
    assert Push.deliver(
             notification(),
             adapter: RecordingAdapter,
             test_pid: self(),
             boundary: :local
           ) == {:ok, %{id: "recorded", duplicate: false}}

    assert_received {:delivered, delivered, opts}
    assert delivered == notification()
    assert opts[:boundary] == :local
    refute Keyword.has_key?(opts, :adapter)
  end

  test "the HTTP adapter rejects incomplete transport configuration without network access" do
    assert Push.deliver(
             notification(),
             adapter: HTTPAdapter,
             endpoint: "http://127.0.0.1:1/push",
             bearer_token: "local-token"
           ) == {:error, {:invalid_option, :receive_timeout}}
  end

  defp notification do
    %{
      idempotency_key: "event-1",
      recipient: "future-device-token",
      title: "Help update",
      body: "A neighbor replied",
      data: %{"kind" => "message"}
    }
  end
end
