defmodule WhoNeedHelp.SocialOAuth.AssentAdapter do
  @moduledoc false

  @behaviour WhoNeedHelp.SocialOAuth

  alias WhoNeedHelp.SocialOAuth.GithubStrategy

  @impl true
  def enabled?(:github), do: not is_nil(provider_config(:github))

  @impl true
  def authorize_url(:github, redirect_uri) do
    with {:ok, config} <- config(:github, redirect_uri) do
      GithubStrategy.authorize_url(config)
    end
  end

  @impl true
  def callback(:github, redirect_uri, params, session_params) do
    with {:ok, config} <- config(:github, redirect_uri),
         {:ok, %{user: user}} <-
           config
           |> Keyword.put(:session_params, session_params)
           |> GithubStrategy.callback(params) do
      normalize_github_identity(user)
    end
  end

  defp config(provider, redirect_uri) do
    case provider_config(provider) do
      nil -> {:error, :provider_disabled}
      config -> {:ok, Keyword.put(config, :redirect_uri, redirect_uri)}
    end
  end

  defp provider_config(provider) do
    :who_need_help
    |> Application.get_env(:social_oauth, %{})
    |> Map.get(provider)
  end

  defp normalize_github_identity(%{
         "sub" => uid,
         "preferred_username" => handle
       })
       when not is_nil(uid) and is_binary(handle) and handle != "" do
    {:ok,
     %{
       provider: :github,
       provider_uid: to_string(uid),
       profile_url: "https://github.com/#{handle}",
       handle: "@#{handle}",
       verified_at: DateTime.utc_now(:second)
     }}
  end

  defp normalize_github_identity(_user), do: {:error, :invalid_provider_identity}
end
