defmodule ToweropsWeb.Org.PreseemInsightsLive do
  @moduledoc false
  use ToweropsWeb, :live_view

  alias Towerops.Preseem
  alias Towerops.Repo

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

    {:ok,
     socket
     |> assign(:organization, org)
     |> assign(:selected_ids, MapSet.new())}
  end

  @impl true
  def handle_params(params, _url, socket) do
    filter_type = params["type"]
    filter_urgency = params["urgency"]
    filter_status = params["status"] || "active"

    {:noreply,
     socket
     |> assign(:filter_type, filter_type)
     |> assign(:filter_urgency, filter_urgency)
     |> assign(:filter_status, filter_status)
     |> assign(:selected_ids, MapSet.new())
     |> load_insights()}
  end

  @impl true
  def handle_event("filter", params, socket) do
    org = socket.assigns.organization

    query_params = %{}

    query_params =
      if params["type"] && params["type"] != "",
        do: Map.put(query_params, "type", params["type"]),
        else: query_params

    query_params =
      if params["urgency"] && params["urgency"] != "",
        do: Map.put(query_params, "urgency", params["urgency"]),
        else: query_params

    query_params =
      if params["status"] && params["status"] != "",
        do: Map.put(query_params, "status", params["status"]),
        else: query_params

    {:noreply,
     push_patch(socket,
       to: ~p"/orgs/#{org.slug}/settings/integrations/preseem/insights?#{query_params}"
     )}
  end

  @impl true
  def handle_event("dismiss", %{"id" => id}, socket) do
    case Preseem.dismiss_insight(id) do
      {:ok, _} ->
        {:noreply,
         socket
         |> load_insights()
         |> put_flash(:info, "Insight dismissed")}

      {:error, _} ->
        {:noreply, put_flash(socket, :error, "Failed to dismiss")}
    end
  end

  @impl true
  def handle_event("toggle_select", %{"id" => id}, socket) do
    selected = socket.assigns.selected_ids

    selected =
      if MapSet.member?(selected, id),
        do: MapSet.delete(selected, id),
        else: MapSet.put(selected, id)

    {:noreply, assign(socket, :selected_ids, selected)}
  end

  @impl true
  def handle_event("select_all", _params, socket) do
    ids = MapSet.new(socket.assigns.insights, & &1.id)
    {:noreply, assign(socket, :selected_ids, ids)}
  end

  @impl true
  def handle_event("deselect_all", _params, socket) do
    {:noreply, assign(socket, :selected_ids, MapSet.new())}
  end

  @impl true
  def handle_event("bulk_dismiss", _params, socket) do
    ids = MapSet.to_list(socket.assigns.selected_ids)

    if ids == [] do
      {:noreply, socket}
    else
      case Preseem.dismiss_insights(ids) do
        {:ok, count} ->
          {:noreply,
           socket
           |> assign(:selected_ids, MapSet.new())
           |> load_insights()
           |> put_flash(:info, "#{count} insight(s) dismissed")}

        {:error, _} ->
          {:noreply, put_flash(socket, :error, "Failed to dismiss insights")}
      end
    end
  end

  defp load_insights(socket) do
    org_id = socket.assigns.organization.id
    opts = [status: socket.assigns.filter_status]

    opts =
      if socket.assigns.filter_type,
        do: Keyword.put(opts, :type, socket.assigns.filter_type),
        else: opts

    opts =
      if socket.assigns.filter_urgency,
        do: Keyword.put(opts, :urgency, socket.assigns.filter_urgency),
        else: opts

    insights =
      org_id
      |> Preseem.list_insights(opts)
      |> Repo.preload([:preseem_access_point, :device])

    assign(socket, :insights, insights)
  end

  defp urgency_classes(urgency) do
    case urgency do
      "critical" ->
        "bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400"

      "warning" ->
        "bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400"

      "info" ->
        "bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-400"

      _ ->
        "bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-400"
    end
  end

  defp selected?(selected_ids, id) do
    MapSet.member?(selected_ids, id)
  end

  defp any_selected?(selected_ids) do
    MapSet.size(selected_ids) > 0
  end
end
