defmodule ToweropsWeb.Admin.AgentLive.IndexTest do
  use ToweropsWeb.ConnCase

  import Phoenix.LiveViewTest

  alias Towerops.Agents

  describe "admin agents page" do
    setup [:register_and_log_in_superuser]

    test "renders page with all agents across organizations", %{conn: conn, user: user} do
      {:ok, org1} = Towerops.Organizations.create_organization(%{name: "Org Alpha"}, user.id)

      {:ok, org2} =
        Towerops.Organizations.create_organization(%{name: "Org Beta"}, user.id, bypass_limits: true)

      {:ok, _agent1, _} = Agents.create_agent_token(org1.id, "Alpha Agent")
      {:ok, _agent2, _} = Agents.create_agent_token(org2.id, "Beta Agent")
      {:ok, _cloud, _} = Agents.create_cloud_poller("Cloud Poller 1")

      {:ok, _view, html} = live(conn, ~p"/admin/agents")

      assert html =~ "All Agents"
      assert html =~ "Alpha Agent"
      assert html =~ "Beta Agent"
      assert html =~ "Cloud Poller 1"
      assert html =~ "Org Alpha"
      assert html =~ "Org Beta"
      assert html =~ "Cloud Poller"
    end

    test "shows cloud badge for cloud pollers", %{conn: conn} do
      {:ok, _cloud, _} = Agents.create_cloud_poller("My Cloud Poller")

      {:ok, _view, html} = live(conn, ~p"/admin/agents")

      assert html =~ "Cloud"
      assert html =~ "My Cloud Poller"
    end

    test "shows debug badge for debug-enabled agents", %{conn: conn, user: user} do
      {:ok, org} = Towerops.Organizations.create_organization(%{name: "Debug Org"}, user.id)
      {:ok, agent, _} = Agents.create_agent_token(org.id, "Debug Agent")
      {:ok, _} = Agents.update_agent_token(agent, %{allow_remote_debug: true})

      {:ok, _view, html} = live(conn, ~p"/admin/agents")

      assert html =~ "Debug"
    end

    test "shows status badges", %{conn: conn, user: user} do
      {:ok, org} = Towerops.Organizations.create_organization(%{name: "Status Org"}, user.id)
      {:ok, _agent, _} = Agents.create_agent_token(org.id, "Status Agent")

      {:ok, _view, html} = live(conn, ~p"/admin/agents")

      assert html =~ "Never connected"
    end

    test "shows version when available", %{conn: conn, user: user} do
      {:ok, org} = Towerops.Organizations.create_organization(%{name: "Version Org"}, user.id)
      {:ok, agent, _} = Agents.create_agent_token(org.id, "Versioned Agent")
      Agents.update_agent_token_heartbeat(agent.id, "10.0.0.1", %{"version" => "1.2.3"})

      {:ok, _view, html} = live(conn, ~p"/admin/agents")

      assert html =~ "v1.2.3"
    end
  end

  describe "real-time updates" do
    setup [:register_and_log_in_superuser]

    test "updates when a new agent is created", %{conn: conn, user: user} do
      {:ok, view, _html} = live(conn, ~p"/admin/agents")

      {:ok, org} = Towerops.Organizations.create_organization(%{name: "New Org"}, user.id)
      {:ok, _agent, _} = Agents.create_agent_token(org.id, "Dynamic Agent")

      html = render(view)
      assert html =~ "Dynamic Agent"
      assert html =~ "New Org"
    end

    test "updates when a new cloud poller is created", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/agents")

      {:ok, _cloud, _} = Agents.create_cloud_poller("Dynamic Cloud Poller")

      html = render(view)
      assert html =~ "Dynamic Cloud Poller"
    end

    test "updates when an agent is deleted", %{conn: conn, user: user} do
      {:ok, org} = Towerops.Organizations.create_organization(%{name: "Delete Org"}, user.id)
      {:ok, agent, _} = Agents.create_agent_token(org.id, "Doomed Agent")

      {:ok, view, html} = live(conn, ~p"/admin/agents")
      assert html =~ "Doomed Agent"

      {:ok, _} = Agents.delete_agent_token(agent.id)

      html = render(view)
      refute html =~ "Doomed Agent"
    end
  end

  describe "non-superuser access" do
    setup [:register_and_log_in_user]

    test "redirects non-superusers", %{conn: conn} do
      assert {:error, {:redirect, %{to: "/orgs"}}} = live(conn, ~p"/admin/agents")
    end
  end

  defp register_and_log_in_superuser(%{conn: conn}) do
    user = Towerops.AccountsFixtures.user_fixture()
    user = Towerops.Repo.update!(Ecto.Changeset.change(user, is_superuser: true))
    %{conn: log_in_user(conn, user), user: user}
  end
end
