defmodule Microwaveprop.Geocoder do
  @moduledoc """
  Thin wrapper around the Google Maps Geocoding API. Only used as a
  fallback when QRZ's own `<lat>` / `<lon>` fields are missing on a
  callsign record.
  """

  @spec geocode(String.t()) :: {:ok, %{lat: float(), lon: float()}} | {:error, String.t()}
  def geocode(address) do
    Microwaveprop.Instrument.span([:geocoder, :geocode], %{}, fn ->
      case Req.get(client(),
             url: "/maps/api/geocode/json",
             params: [address: address, key: api_key()]
           ) do
        {:ok, %{status: 200, body: %{"status" => "OK", "results" => [first | _]}}} ->
          %{"geometry" => %{"location" => %{"lat" => lat, "lng" => lon}}} = first
          {:ok, %{lat: lat, lon: lon}}

        {:ok, %{status: 200, body: %{"status" => "ZERO_RESULTS"}}} ->
          {:error, "No results found"}

        {:ok, %{status: 200, body: %{"status" => status}}} ->
          {:error, "Geocoding failed: #{status}"}

        {:error, reason} ->
          {:error, "Geocoding request failed: #{inspect(reason)}"}
      end
    end)
  end

  defp client do
    config = Application.get_env(:microwaveprop, __MODULE__, [])

    [base_url: "https://maps.googleapis.com"]
    |> Req.new()
    |> Req.Request.register_options([:plug, :api_key])
    |> Req.merge(config)
  end

  defp api_key do
    :microwaveprop
    |> Application.get_env(__MODULE__, [])
    |> Keyword.get(:api_key, "")
  end
end
