defmodule Microwaveprop.Radio.CallsignClientTest do
  use Microwaveprop.DataCase, async: false

  alias Microwaveprop.CallsignLocation.Location
  alias Microwaveprop.Qrz.Client
  alias Microwaveprop.Radio.CallsignClient

  setup do
    Client.reset_session()
    :ok
  end

  describe "locate/1" do
    test "reshapes a cached CallsignLocation into the public shape" do
      {:ok, _} =
        %Location{}
        |> Location.changeset(%{
          callsign: "W1AW",
          latitude: 41.714,
          longitude: -72.727,
          gridsquare: "FN31pr58"
        })
        |> Repo.insert()

      assert {:ok, result} = CallsignClient.locate("W1AW")

      assert result == %{
               callsign: "W1AW",
               gridsquare: "FN31pr58",
               lat: 41.714,
               lon: -72.727
             }
    end

    test "returns only callsign, gridsquare, lat, lon (drops name and address)" do
      {:ok, _} =
        %Location{}
        |> Location.changeset(%{
          callsign: "W1AW",
          latitude: 41.714,
          longitude: -72.727,
          gridsquare: "FN31pr58"
        })
        |> Repo.insert()

      assert {:ok, result} = CallsignClient.locate("W1AW")

      assert result |> Map.keys() |> Enum.sort() == [:callsign, :gridsquare, :lat, :lon]
    end

    test "renames latitude/longitude to lat/lon" do
      {:ok, _} =
        %Location{}
        |> Location.changeset(%{
          callsign: "K5QE",
          latitude: 30.5,
          longitude: -94.1,
          gridsquare: "EM30wn"
        })
        |> Repo.insert()

      assert {:ok, %{lat: 30.5, lon: -94.1}} = CallsignClient.locate("K5QE")
    end

    test "propagates {:error, reason} tuples from the underlying lookup" do
      Req.Test.expect(Client, 2, fn conn ->
        params = Plug.Conn.fetch_query_params(conn).query_params

        if Map.has_key?(params, "username") do
          Plug.Conn.send_resp(conn, 200, """
          <?xml version="1.0" encoding="utf-8"?>
          <QRZDatabase version="1.34">
            <Session><Key>session123</Key></Session>
          </QRZDatabase>
          """)
        else
          Plug.Conn.send_resp(conn, 200, """
          <?xml version="1.0" encoding="utf-8"?>
          <QRZDatabase version="1.34">
            <Session>
              <Error>Not found: INVALID</Error>
              <Key>session123</Key>
            </Session>
          </QRZDatabase>
          """)
        end
      end)

      assert {:error, _reason} = CallsignClient.locate("INVALID")
    end

    test "upcases lookups, matching a cached row inserted in different casing" do
      # The underlying CallsignLocation.lookup/1 upcases the callsign before
      # the DB read, so a mixed-case request finds an uppercase cache hit.
      {:ok, _} =
        %Location{}
        |> Location.changeset(%{
          callsign: "W1AW",
          latitude: 41.714,
          longitude: -72.727,
          gridsquare: "FN31pr58"
        })
        |> Repo.insert()

      assert {:ok, %{callsign: "W1AW"}} = CallsignClient.locate("w1aw")
    end
  end
end
