defmodule TarakanWeb.AdminLive.Index do
  use TarakanWeb, :live_view

  alias Tarakan.Accounts
  alias Tarakan.Policy
  alias TarakanWeb.AccountAuth

  @impl true
  def mount(_params, _session, socket) do
    scope = socket.assigns.current_scope

    cond do
      not Policy.allowed?(scope, :administer) ->
        {:ok, unauthorized(socket)}

      not Accounts.sudo_mode?(scope.account) ->
        {:ok,
         socket
         |> put_flash(:error, "Confirm it's you before opening platform administration.")
         |> redirect(to: AccountAuth.reauth_path(~p"/admin"))}

      true ->
        with {:ok, accounts} <- Accounts.list_accounts_for_admin(scope),
             {:ok, summary} <- Accounts.account_admin_summary(scope) do
          {:ok,
           socket
           |> assign(:page_title, "Platform administration")
           |> assign(:summary, summary)
           |> assign(:account_count, length(accounts))
           |> assign(:filter_form, to_form(%{"query" => ""}, as: :filters))
           |> stream(:accounts, accounts)}
        else
          {:error, _reason} -> {:ok, unauthorized(socket)}
        end
    end
  end

  @impl true
  def handle_event("filter", %{"filters" => %{"query" => query}}, socket) do
    with_recent_auth(socket, fn ->
      case Accounts.list_accounts_for_admin(socket.assigns.current_scope, query) do
        {:ok, accounts} ->
          {:noreply,
           socket
           |> assign(:account_count, length(accounts))
           |> assign(:filter_form, to_form(%{"query" => query}, as: :filters))
           |> stream(:accounts, accounts, reset: true)}

        {:error, _reason} ->
          {:noreply, unauthorized(socket)}
      end
    end)
  end

  def handle_event("filter", _params, socket), do: {:noreply, socket}

  # The mount-time sudo check only covers the initial render; a long-lived
  # LiveView can outlast the two-hour window, so admin events re-check.
  defp with_recent_auth(socket, fun) do
    if Accounts.sudo_mode?(socket.assigns.current_scope.account) do
      fun.()
    else
      {:noreply,
       socket
       |> put_flash(:error, "Confirm it's you before opening platform administration.")
       |> push_navigate(to: AccountAuth.reauth_path(~p"/admin"))}
    end
  end

  defp unauthorized(socket) do
    socket
    |> put_flash(:error, "Administrator access is required.")
    |> redirect(to: ~p"/")
  end
end
