defmodule ToweropsWeb.AlertLive.IndexTest do
  use ToweropsWeb.ConnCase

  import Phoenix.LiveViewTest

  setup :register_and_log_in_user

  setup %{user: user} do
    {:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id)

    {:ok, site} =
      Towerops.Sites.create_site(%{
        name: "Test Site",
        organization_id: organization.id
      })

    {:ok, device} =
      Towerops.Devices.create_device(%{
        name: "Test Router",
        ip_address: "192.168.1.1",
        site_id: site.id,
        organization_id: organization.id
      })

    %{organization: organization, site: site, device: device}
  end

  describe "Index" do
    test "displays alerts page", %{conn: conn, organization: _organization} do
      {:ok, _view, html} = live(conn, ~p"/alerts")

      assert html =~ "Alerts"
      assert html =~ "Monitor and acknowledge system alerts"
    end

    test "displays empty state when no alerts", %{conn: conn, organization: _organization} do
      {:ok, _view, html} = live(conn, ~p"/alerts")

      assert html =~ "No alerts"
    end

    test "lists all alerts", %{conn: conn, organization: _organization, device: device} do
      {:ok, _alert} =
        Towerops.Alerts.create_alert(%{
          device_id: device.id,
          alert_type: :device_down,
          triggered_at: DateTime.utc_now(),
          message: "Device is down"
        })

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

      assert html =~ "Test Router"
      assert html =~ "Device is down"
      assert html =~ "Device Down"
    end

    test "filters active alerts", %{conn: conn, organization: _organization, device: device} do
      # Create an active equipment_down alert
      {:ok, _active_alert} =
        Towerops.Alerts.create_alert(%{
          device_id: device.id,
          alert_type: :device_down,
          triggered_at: DateTime.utc_now(),
          message: "Device is down"
        })

      # Create a recovery alert (device_up)
      {:ok, _recovery_alert} =
        Towerops.Alerts.create_alert(%{
          device_id: device.id,
          alert_type: :device_up,
          triggered_at: DateTime.utc_now(),
          message: "Device recovered"
        })

      {:ok, _view, html} =
        live(conn, ~p"/alerts?filter=active")

      # Should show equipment_down alert
      assert html =~ "Device is down"
      # Should NOT show equipment_up alert in active filter
      refute html =~ "Device recovered"
    end

    test "acknowledges an alert", %{conn: conn, organization: _organization, device: device} do
      {:ok, alert} =
        Towerops.Alerts.create_alert(%{
          device_id: device.id,
          alert_type: :device_down,
          triggered_at: DateTime.utc_now(),
          message: "Device is down"
        })

      {:ok, view, _html} = live(conn, ~p"/alerts")

      html =
        view
        |> element("button", "Acknowledge")
        |> render_click(%{"id" => alert.id})

      assert html =~ "Alert acknowledged"
    end

    test "does not show acknowledge button for device_up alerts", %{
      conn: conn,
      organization: _organization,
      device: device
    } do
      {:ok, _alert} =
        Towerops.Alerts.create_alert(%{
          device_id: device.id,
          alert_type: :device_up,
          triggered_at: DateTime.utc_now(),
          message: "Device recovered"
        })

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

      # Should not show acknowledge button for device_up alerts
      refute html =~ "Acknowledge"
    end

    test "updates in real-time when new alert is created", %{
      conn: conn,
      organization: organization,
      device: device
    } do
      {:ok, view, _html} = live(conn, ~p"/alerts")

      # Broadcast new alert event on org-scoped topic
      Phoenix.PubSub.broadcast(
        Towerops.PubSub,
        "alerts:org:#{organization.id}:new",
        {:new_alert, device.id, :device_down}
      )

      # View should update
      assert render(view)
    end

    test "updates in real-time when alert is resolved", %{
      conn: conn,
      organization: organization,
      device: device
    } do
      {:ok, alert} =
        Towerops.Alerts.create_alert(%{
          device_id: device.id,
          alert_type: :device_down,
          triggered_at: DateTime.utc_now(),
          message: "Device is down"
        })

      {:ok, view, _html} = live(conn, ~p"/alerts")

      # Resolve the alert and broadcast
      Towerops.Alerts.resolve_alert(alert)

      Phoenix.PubSub.broadcast(
        Towerops.PubSub,
        "alerts:org:#{organization.id}:resolved",
        {:alert_resolved, device.id, :device_down}
      )

      # View should update
      assert render(view)
    end

    test "requires authentication", %{organization: _organization} do
      conn = build_conn()
      {:error, redirect} = live(conn, ~p"/alerts")

      assert {:redirect, %{to: path}} = redirect
      assert path == ~p"/users/log-in"
    end

    test "shows site subscriber context when Gaiia mapped", %{
      conn: conn,
      organization: organization,
      site: site,
      device: device
    } do
      {:ok, _alert} =
        Towerops.Alerts.create_alert(%{
          device_id: device.id,
          alert_type: :device_down,
          triggered_at: DateTime.utc_now(),
          message: "Device is down"
        })

      {:ok, _} =
        Towerops.Gaiia.upsert_network_site(organization.id, %{
          gaiia_id: "ns-alert-test",
          name: "Tower",
          account_count: 75,
          total_mrr: Decimal.new("3750.00"),
          site_id: site.id
        })

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

      assert html =~ "75 subscribers"
      assert html =~ "3,750"
    end

    test "hides site subscriber context when no Gaiia mapping", %{
      conn: conn,
      device: device
    } do
      {:ok, _alert} =
        Towerops.Alerts.create_alert(%{
          device_id: device.id,
          alert_type: :device_down,
          triggered_at: DateTime.utc_now(),
          message: "Device is down"
        })

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

      refute html =~ "subscribers"
      refute html =~ "MRR"
    end
  end
end
