defmodule Towerops.Monitoring.SupervisorTest do
  use Towerops.DataCase, async: false

  import Towerops.AccountsFixtures

  alias Towerops.Monitoring.Supervisor, as: MonitoringSupervisor
  alias Towerops.Snmp.PollerRegistry

  setup do
    user = user_fixture()
    {: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: "Router 1",
        ip_address: "192.168.1.1",
        site_id: site.id,
        monitoring_enabled: true
      })

    %{device: device, site: site}
  end

  describe "start_monitor/1" do
    test "starts a monitor for device", %{device: device} do
      assert {:ok, pid} = MonitoringSupervisor.start_monitor(device.id)
      assert is_pid(pid)
      assert Process.alive?(pid)

      # Cleanup
      MonitoringSupervisor.stop_monitor(device.id)
    end

    test "returns error when monitor already running", %{device: device} do
      {:ok, _pid} = MonitoringSupervisor.start_monitor(device.id)

      assert {:error, {:already_started, _pid}} =
               MonitoringSupervisor.start_monitor(device.id)

      # Cleanup
      MonitoringSupervisor.stop_monitor(device.id)
    end
  end

  describe "stop_monitor/1" do
    test "stops a running monitor", %{device: device} do
      {:ok, pid} = MonitoringSupervisor.start_monitor(device.id)
      assert Process.alive?(pid)

      assert :ok = MonitoringSupervisor.stop_monitor(device.id)

      # Give it a moment to terminate
      Process.sleep(10)
      refute Process.alive?(pid)
    end

    test "returns :ok when monitor not running", %{device: device} do
      assert :ok = MonitoringSupervisor.stop_monitor(device.id)
    end
  end

  describe "start_snmp_poller/1" do
    test "starts an SNMP poller for device", %{device: device} do
      # Enable SNMP for the equipment
      {:ok, device} =
        Towerops.Devices.update_device(device, %{
          snmp_enabled: true,
          snmp_community: "public"
        })

      assert {:ok, pid} = MonitoringSupervisor.start_snmp_poller(device.id)
      assert is_pid(pid)
      assert Process.alive?(pid)

      # Cleanup
      MonitoringSupervisor.stop_snmp_poller(device.id)
    end

    test "returns error when poller already running", %{device: device} do
      {:ok, device} =
        Towerops.Devices.update_device(device, %{
          snmp_enabled: true,
          snmp_community: "public"
        })

      {:ok, _pid} = MonitoringSupervisor.start_snmp_poller(device.id)

      assert {:error, {:already_started, _pid}} =
               MonitoringSupervisor.start_snmp_poller(device.id)

      # Cleanup
      MonitoringSupervisor.stop_snmp_poller(device.id)
    end
  end

  describe "stop_snmp_poller/1" do
    test "stops a running SNMP poller", %{device: device} do
      {:ok, device} =
        Towerops.Devices.update_device(device, %{
          snmp_enabled: true,
          snmp_community: "public"
        })

      {:ok, pid} = MonitoringSupervisor.start_snmp_poller(device.id)
      assert Process.alive?(pid)

      assert :ok = MonitoringSupervisor.stop_snmp_poller(device.id)

      # Give it a moment to terminate
      Process.sleep(10)
      refute Process.alive?(pid)
    end

    test "returns :ok when poller not running", %{device: device} do
      assert :ok = MonitoringSupervisor.stop_snmp_poller(device.id)
    end
  end

  describe "start_all_monitors/0" do
    test "starts monitors for all monitored devices", %{device: device, site: site} do
      # Create another monitored device
      {:ok, device2} =
        Towerops.Devices.create_device(%{
          name: "Router 2",
          ip_address: "192.168.1.2",
          site_id: site.id,
          monitoring_enabled: true
        })

      # Start all monitors
      MonitoringSupervisor.start_all_monitors()

      # Check that both are running
      assert [{pid1, _}] = Registry.lookup(Towerops.Monitoring.Registry, device.id)
      assert [{pid2, _}] = Registry.lookup(Towerops.Monitoring.Registry, device2.id)
      assert Process.alive?(pid1)
      assert Process.alive?(pid2)

      # Cleanup
      MonitoringSupervisor.stop_monitor(device.id)
      MonitoringSupervisor.stop_monitor(device2.id)
    end
  end

  describe "start_all_snmp_pollers/0" do
    test "starts pollers for all SNMP-enabled devices", %{device: device, site: site} do
      # Enable SNMP on device
      {:ok, _} =
        Towerops.Devices.update_device(device, %{
          snmp_enabled: true,
          snmp_community: "public"
        })

      # Create another SNMP-enabled device
      {:ok, device2} =
        Towerops.Devices.create_device(%{
          name: "Router 2",
          ip_address: "192.168.1.2",
          site_id: site.id,
          snmp_enabled: true,
          snmp_community: "public"
        })

      # Start all pollers
      MonitoringSupervisor.start_all_snmp_pollers()

      # Check that both are running
      assert [{pid1, _}] = Registry.lookup(PollerRegistry, device.id)
      assert [{pid2, _}] = Registry.lookup(PollerRegistry, device2.id)
      assert Process.alive?(pid1)
      assert Process.alive?(pid2)

      # Cleanup
      MonitoringSupervisor.stop_snmp_poller(device.id)
      MonitoringSupervisor.stop_snmp_poller(device2.id)
    end
  end
end
