defmodule ToweropsWeb.Admin.MonitoringLiveTest do
  use ToweropsWeb.ConnCase

  import Phoenix.LiveViewTest
  import Towerops.DevicesFixtures
  import Towerops.JobsFixtures

  describe "MonitoringLive" do
    setup [:register_and_log_in_superuser]

    test "renders monitoring dashboard", %{conn: conn} do
      {:ok, _view, html} = live(conn, ~p"/admin/monitoring")

      assert html =~ "Job Monitoring Dashboard"
      assert html =~ "Active Operations"
      assert html =~ "Problems"
      assert html =~ "Health Metrics"
    end

    test "subscribes to job lifecycle events", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/monitoring")

      # Verify PubSub subscription by checking it's alive
      assert Process.alive?(view.pid)
    end

    test "displays active operations section", %{conn: conn} do
      {:ok, _view, html} = live(conn, ~p"/admin/monitoring")

      assert html =~ "Active Operations"
      assert html =~ "No jobs currently executing"
    end
  end

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

    test "displays executing jobs from database", %{conn: conn} do
      device = device_fixture()

      _job =
        oban_job_fixture(%{
          worker: "Towerops.Workers.DevicePollerWorker",
          state: "executing",
          args: %{"device_id" => device.id},
          attempted_at: DateTime.utc_now()
        })

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

      # Should show the device name in executing jobs
      assert html =~ device.name
      assert html =~ "Active Operations (1)"
    end
  end

  describe "metrics display" do
    setup [:register_and_log_in_superuser]

    test "shows current activity metrics", %{conn: conn} do
      device = device_fixture()

      oban_job_fixture(%{
        worker: "Towerops.Workers.DevicePollerWorker",
        state: "executing",
        args: %{"device_id" => device.id}
      })

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

      assert html =~ "Executing"
      assert html =~ "1"
    end
  end

  describe "handle_info events" do
    setup [:register_and_log_in_superuser]

    test "handles job started event", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/monitoring")

      send(view.pid, %{event: :started, job_id: 1, worker: "TestWorker"})

      assert render(view)
    end

    test "handles job completed event", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/monitoring")

      send(view.pid, %{event: :completed, job_id: 1, worker: "TestWorker"})

      assert render(view)
    end

    test "handles job failed event", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/monitoring")

      send(view.pid, %{event: :failed, job_id: 1, worker: "TestWorker"})

      assert render(view)
    end

    test "handles unknown events gracefully", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/monitoring")

      send(view.pid, :some_unknown_event)

      assert render(view)
    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
