defmodule Web.AdminAuth do
  @moduledoc false
  use Web, :verified_routes

  import Phoenix.Controller
  import Plug.Conn

  def log_in_admin(conn, params) do
    conn
    |> renew_session()
    |> put_session(:admin?, true)
    |> redirect(to: params["return_to"] || ~p"/admin")
  end

  def log_out_admin(conn, params) do
    if live_socket_id = get_session(conn, :live_socket_id) do
      Web.Endpoint.broadcast(live_socket_id, "disconnect", %{})
    end

    conn
    |> renew_session()
    |> redirect(to: params["return_to"] || ~p"/")
  end

  def mount_admin(%Plug.Conn{} = conn, _opts) do
    assign(conn, :admin?, admin?(conn))
  end

  def require_admin(%Plug.Conn{assigns: %{admin?: true}} = conn, _opts) do
    conn
  end

  def require_admin(conn, _opts) do
    redirect(conn, to: ~p"/sign-in?return_to=#{conn.request_path}")
  end

  def correct_password?(password) do
    password_hash = Application.fetch_env!(:sloanely_but_surely, :password_hash)

    Argon2.verify_pass(password, password_hash)
  end

  def on_mount(:default, _params, session, socket) do
    {:cont, Phoenix.Component.assign(socket, :admin?, admin?(session))}
  end

  ## private

  defp renew_session(conn) do
    delete_csrf_token()

    conn
    |> configure_session(renew: true)
    |> clear_session()
  end

  defp admin?(%Plug.Conn{} = conn) do
    Plug.Conn.get_session(conn, :admin?, false) == true
  end

  defp admin?(%{} = session), do: Map.get(session, "admin?", false) == true
end