# Copyright 2018-2019 OmiseGO Pte Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

defmodule EWalletAPI.V1.AuthController do
  use EWalletAPI, :controller
  import EWalletAPI.V1.ErrorHandler
  alias EWalletAPI.V1.{ClientAuthPlug, EndUserAuthenticator}
  alias EWallet.Web.{Orchestrator, Originator, V1.AuthTokenOverlay}
  alias EWalletDB.{AuthToken, User}

  @doc """
  Logins the user.

  This function is used when the eWallet is setup as a standalone solution,
  allowing users to log in without an integration with the provider's server.
  """
  def login(conn, attrs) do
    with email when is_binary(email) <- attrs["email"] || {:error, :missing_email},
         password when is_binary(password) <- attrs["password"] || {:error, :missing_password},
         conn <- EndUserAuthenticator.authenticate(conn, email, password),
         true <- conn.assigns.authenticated || {:error, :invalid_login_credentials},
         true <-
           User.get_status(conn.assigns.end_user) == :active || {:error, :email_not_verified},
         originator <- Originator.extract(conn.assigns),
         {:ok, auth_token} <-
           AuthToken.generate(conn.assigns.end_user, :ewallet_api, originator),
         {:ok, auth_token} = Orchestrator.one(auth_token, AuthTokenOverlay, attrs) do
      render(conn, :auth_token, %{auth_token: auth_token})
    else
      {:error, code} ->
        handle_error(conn, code)
    end
  end

  @doc """
  Invalidates the authentication token used in this request.

  Note that this function can logout the user sessions generated by both
  the Admin API and the eWallet API.
  """
  def logout(conn, _attrs) do
    conn
    |> ClientAuthPlug.expire_token()
    |> render(:empty_response, %{})
  end
end
