defmodule WhoNeedHelp.SocialOAuth do
  @moduledoc """
  Provider-neutral boundary for verifying social identities.

  OAuth access tokens are consumed by the configured adapter and are never
  returned to controllers or persisted by this application.
  """

  @type provider :: :github
  @type session_params :: map()
  @type verified_identity :: %{
          provider: provider(),
          provider_uid: String.t(),
          profile_url: String.t(),
          handle: String.t() | nil,
          verified_at: DateTime.t()
        }

  @callback enabled?(provider()) :: boolean()
  @callback authorize_url(provider(), String.t()) ::
              {:ok, %{url: String.t(), session_params: session_params()}} | {:error, term()}
  @callback callback(provider(), String.t(), map(), session_params()) ::
              {:ok, verified_identity()} | {:error, term()}

  def provider("github"), do: {:ok, :github}
  def provider(_provider), do: {:error, :unsupported_provider}

  def enabled?(provider), do: adapter().enabled?(provider)

  def authorize_url(provider, redirect_uri),
    do: adapter().authorize_url(provider, redirect_uri)

  def callback(provider, redirect_uri, params, session_params),
    do: adapter().callback(provider, redirect_uri, params, session_params)

  defp adapter do
    Application.get_env(
      :who_need_help,
      :social_oauth_adapter,
      WhoNeedHelp.SocialOAuth.AssentAdapter
    )
  end
end
