defmodule Towerops.Agents.CloudPollerTest do
  use Towerops.DataCase

  import Towerops.AccountsFixtures
  import Towerops.OrganizationsFixtures

  alias Towerops.Agents
  alias Towerops.Repo
  alias Towerops.Sites

  describe "list_online_cloud_pollers/0" do
    test "returns cloud pollers seen within 5 minutes" do
      {:ok, cloud_poller, _token} = Agents.create_cloud_poller("Cloud 1")

      cloud_poller
      |> Ecto.Changeset.change(%{last_seen_at: DateTime.truncate(DateTime.utc_now(), :second)})
      |> Repo.update!()

      pollers = Agents.list_online_cloud_pollers()

      assert length(pollers) == 1
      assert hd(pollers).id == cloud_poller.id
    end

    test "excludes cloud pollers not seen recently" do
      {:ok, cloud_poller, _token} = Agents.create_cloud_poller("Stale Cloud")

      ten_min_ago = DateTime.utc_now() |> DateTime.add(-10, :minute) |> DateTime.truncate(:second)

      cloud_poller
      |> Ecto.Changeset.change(%{last_seen_at: ten_min_ago})
      |> Repo.update!()

      assert Agents.list_online_cloud_pollers() == []
    end

    test "excludes disabled cloud pollers" do
      {:ok, cloud_poller, _token} = Agents.create_cloud_poller("Disabled Cloud")

      cloud_poller
      |> Ecto.Changeset.change(%{
        last_seen_at: DateTime.truncate(DateTime.utc_now(), :second),
        enabled: false
      })
      |> Repo.update!()

      assert Agents.list_online_cloud_pollers() == []
    end

    test "excludes regular (non-cloud) agents" do
      user = user_fixture()
      org = organization_fixture(user.id)
      {:ok, agent, _token} = Agents.create_agent_token(org.id, "Regular Agent")

      agent
      |> Ecto.Changeset.change(%{last_seen_at: DateTime.truncate(DateTime.utc_now(), :second)})
      |> Repo.update!()

      assert Agents.list_online_cloud_pollers() == []
    end
  end

  describe "list_cloud_polled_devices/0" do
    test "returns devices with no agent assignment" do
      user = user_fixture()
      org = organization_fixture(user.id)
      {:ok, site} = Sites.create_site(%{name: "Test Site", organization_id: org.id})

      {:ok, device} =
        Towerops.Devices.create_device(%{
          name: "Unassigned Router",
          ip_address: "192.168.1.1",
          site_id: site.id,
          organization_id: org.id,
          snmp_enabled: true,
          snmp_community: "public",
          snmp_version: "2c",
          monitoring_enabled: true
        })

      devices = Agents.list_cloud_polled_devices()

      assert length(devices) == 1
      assert hd(devices).id == device.id
    end

    test "returns devices assigned to a cloud poller" do
      user = user_fixture()
      org = organization_fixture(user.id)
      {:ok, cloud_poller, _token} = Agents.create_cloud_poller("Cloud 1")
      {:ok, site} = Sites.create_site(%{name: "Test Site", organization_id: org.id})

      {:ok, device} =
        Towerops.Devices.create_device(%{
          name: "Cloud Polled Router",
          ip_address: "192.168.1.1",
          site_id: site.id,
          organization_id: org.id,
          snmp_enabled: true,
          snmp_community: "public",
          snmp_version: "2c",
          monitoring_enabled: true
        })

      {:ok, _} = Agents.assign_device_to_agent(cloud_poller.id, device.id)

      devices = Agents.list_cloud_polled_devices()

      assert length(devices) == 1
      assert hd(devices).id == device.id
    end

    test "excludes devices assigned to a local agent" do
      user = user_fixture()
      org = organization_fixture(user.id)
      {:ok, local_agent, _token} = Agents.create_agent_token(org.id, "Local Agent")
      {:ok, site} = Sites.create_site(%{name: "Test Site", organization_id: org.id})

      {:ok, device} =
        Towerops.Devices.create_device(%{
          name: "Local Router",
          ip_address: "192.168.1.1",
          site_id: site.id,
          organization_id: org.id,
          snmp_enabled: true,
          snmp_community: "public",
          snmp_version: "2c",
          monitoring_enabled: true
        })

      {:ok, _} = Agents.assign_device_to_agent(local_agent.id, device.id)

      assert Agents.list_cloud_polled_devices() == []
    end

    test "excludes devices with monitoring disabled" do
      user = user_fixture()
      org = organization_fixture(user.id)
      {:ok, site} = Sites.create_site(%{name: "Test Site", organization_id: org.id})

      {:ok, _device} =
        Towerops.Devices.create_device(%{
          name: "No Monitoring Router",
          ip_address: "192.168.1.1",
          site_id: site.id,
          organization_id: org.id,
          snmp_enabled: true,
          snmp_community: "public",
          snmp_version: "2c",
          monitoring_enabled: false
        })

      assert Agents.list_cloud_polled_devices() == []
    end

    test "includes devices whose site default is a cloud poller" do
      user = user_fixture()
      org = organization_fixture(user.id)
      {:ok, cloud_poller, _token} = Agents.create_cloud_poller("Cloud 1")

      {:ok, site} =
        Sites.create_site(%{
          name: "Cloud Site",
          organization_id: org.id,
          agent_token_id: cloud_poller.id
        })

      {:ok, device} =
        Towerops.Devices.create_device(%{
          name: "Site Cloud Router",
          ip_address: "192.168.1.1",
          site_id: site.id,
          organization_id: org.id,
          snmp_enabled: true,
          snmp_community: "public",
          snmp_version: "2c",
          monitoring_enabled: true
        })

      devices = Agents.list_cloud_polled_devices()

      assert length(devices) == 1
      assert hd(devices).id == device.id
    end

    test "excludes devices whose site default is a local agent" do
      user = user_fixture()
      org = organization_fixture(user.id)
      {:ok, local_agent, _token} = Agents.create_agent_token(org.id, "Local Agent")

      {:ok, site} =
        Sites.create_site(%{
          name: "Local Site",
          organization_id: org.id,
          agent_token_id: local_agent.id
        })

      {:ok, _device} =
        Towerops.Devices.create_device(%{
          name: "Site Local Router",
          ip_address: "192.168.1.1",
          site_id: site.id,
          organization_id: org.id,
          snmp_enabled: true,
          snmp_community: "public",
          snmp_version: "2c",
          monitoring_enabled: true
        })

      assert Agents.list_cloud_polled_devices() == []
    end
  end
end
