defmodule ToweropsWeb.UserSettingsLive.SessionManager do
  @moduledoc """
  Handles browser session and mobile device session management.
  """
  use Gettext, backend: ToweropsWeb.Gettext

  import ToweropsWeb.GettextHelpers

  alias Towerops.Accounts
  alias Towerops.MobileSessions

  @doc """
  Revokes a mobile device session.
  """
  def revoke_mobile_device(socket, session_id) do
    case MobileSessions.revoke_session(session_id) do
      {:ok, _} ->
        socket
        |> Phoenix.LiveView.put_flash(:info, t_auth("Mobile device removed successfully."))
        |> assign_mobile_sessions()

      {:error, _} ->
        Phoenix.LiveView.put_flash(socket, :error, t_auth("Failed to remove mobile device."))
    end
  end

  @doc """
  Toggles alert preferences for a mobile device.
  """
  def toggle_device_alerts(socket, session_id, enabled) do
    enabled_bool = enabled == "true"

    case MobileSessions.update_alert_preferences(session_id, %{alerts_enabled: enabled_bool}) do
      {:ok, _} ->
        message = if enabled_bool, do: t_auth("Alerts enabled for device"), else: t_auth("Alerts disabled for device")

        socket
        |> Phoenix.LiveView.put_flash(:info, message)
        |> assign_mobile_sessions()

      {:error, _} ->
        Phoenix.LiveView.put_flash(socket, :error, t_auth("Failed to update alert preferences."))
    end
  end

  @doc """
  Revokes a browser session.
  """
  def revoke_session(socket, session_id) do
    user = socket.assigns.current_scope.user
    current_token_id = get_current_token_id(socket)

    case Accounts.revoke_browser_session(session_id, user.id, current_token_id) do
      {:ok, _} ->
        socket
        |> Phoenix.LiveView.put_flash(:info, t_auth("Session revoked successfully."))
        |> assign_browser_sessions()

      {:error, :self_revoke} ->
        Phoenix.LiveView.put_flash(socket, :error, t_auth("You cannot revoke your current session."))

      {:error, :not_found} ->
        Phoenix.LiveView.put_flash(socket, :error, t_auth("Session not found."))

      {:error, _} ->
        Phoenix.LiveView.put_flash(socket, :error, t_auth("Failed to revoke session."))
    end
  end

  @doc """
  Shows the revoke all sessions confirmation modal.
  """
  def show_revoke_all_modal(socket) do
    Phoenix.Component.assign(socket, :show_revoke_all_modal, true)
  end

  @doc """
  Cancels revoking all sessions.
  """
  def cancel_revoke_all(socket) do
    Phoenix.Component.assign(socket, :show_revoke_all_modal, false)
  end

  @doc """
  Confirms and revokes all other sessions except the current one.
  """
  def confirm_revoke_all(socket) do
    user = socket.assigns.current_scope.user
    current_token_id = get_current_token_id(socket)

    {count, _} = Accounts.revoke_all_other_sessions(user.id, current_token_id)

    socket
    |> Phoenix.LiveView.put_flash(:info, t_auth("Revoked %{count} other session(s) successfully.", count: count))
    |> Phoenix.Component.assign(:show_revoke_all_modal, false)
    |> assign_browser_sessions()
  end

  @doc """
  Assigns mobile sessions to socket.
  """
  def assign_mobile_sessions(socket) do
    user = socket.assigns.current_scope.user
    Phoenix.Component.assign(socket, :mobile_sessions, MobileSessions.list_user_sessions(user.id))
  end

  @doc """
  Assigns browser sessions to socket.
  """
  def assign_browser_sessions(socket) do
    user = socket.assigns.current_scope.user
    sessions = Accounts.list_active_browser_sessions(user.id)
    Phoenix.Component.assign(socket, :browser_sessions, sessions)
  end

  @doc """
  Gets the current token ID from socket assigns.
  """
  def get_current_token_id(%{assigns: %{current_token: token}}) when is_binary(token) do
    Accounts.get_user_token_id_by_value(token)
  end

  def get_current_token_id(_), do: nil
end
