defmodule MongoosePush.API.V3FCMTest do
  use ExUnit.Case, async: false
  alias MongoosePush.Support.API, as: Tools

  @url "/v3/notification/f534534543"

  setup do
    if Mix.env() == :test do
      TestHelper.reload_app(backend_module: MongoosePush)
    end

    Tools.reset(:fcm)
    :ok
  end

  @tag integration: true
  test "push to fcm with id mismatch fails" do
    reason = "SENDER_ID_MISMATCH"

    Tools.mock_fcm("/error-tokens", [%{device_token: "f534534543", status: 403, reason: reason}])

    assert {503, %{"reason" => "service_internal"}} ==
             Tools.post(@url, Tools.sample_notification(:fcm))
  end

  @tag integration: true
  test "push to fcm with unregistered token fails" do
    reason = "UNREGISTERED"

    Tools.mock_fcm("/error-tokens", [%{device_token: "f534534543", status: 404, reason: reason}])

    assert {410, %{"reason" => "unregistered"}} ==
             Tools.post(@url, Tools.sample_notification(:fcm))
  end

  @tag integration: true
  test "push to fcm with the limit exceeded fails" do
    reason = "QUOTA_EXCEEDED"

    Tools.mock_fcm("/error-tokens", [%{device_token: "f534534543", status: 429, reason: reason}])

    assert {429, %{"reason" => "too_many_requests"}} ==
             Tools.post(@url, Tools.sample_notification(:fcm))
  end

  @tag integration: true
  test "push to fcm fails with unknown internal error" do
    reason = "INTERNAL"

    Tools.mock_fcm("/error-tokens", [%{device_token: "f534534543", status: 500, reason: reason}])

    assert {503, %{"reason" => "service_internal"}} ==
             Tools.post(@url, Tools.sample_notification(:fcm))
  end

  @tag integration: true
  test "push to fcm with invalid or missing certificate/web push fails" do
    reason = "THIRD_PARTY_AUTH_ERROR"

    Tools.mock_fcm("/error-tokens", [%{device_token: "f534534543", status: 401, reason: reason}])

    assert {503, %{"reason" => "service_internal"}} ==
             Tools.post(@url, Tools.sample_notification(:fcm))
  end

  @tag integration: true
  test "push to fcm fails when service is unavailable/overloaded" do
    reason = "UNAVAILABLE"

    Tools.mock_fcm("/error-tokens", [%{device_token: "f534534543", status: 503, reason: reason}])

    assert {503, %{"reason" => "service_internal"}} ==
             Tools.post(@url, Tools.sample_notification(:fcm))
  end

  @tag integration: true
  test "push to fcm succeeds" do
    Tools.reset(:fcm)

    assert {200, nil} == Tools.post(@url, Tools.sample_notification(:fcm))
  end

  @tag integration: true
  test "push to fcm with bad notification format fails" do
    Tools.reset(:fcm)

    assert {400, %{"reason" => "invalid_notification"}} ==
             Tools.post(@url, Tools.sample_bad_notification(:fcm))
  end
end
