defmodule Towerops.Devices.DeviceStatusCountsTest do
  use Towerops.DataCase, async: true

  import Towerops.AccountsFixtures

  alias Towerops.Devices

  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
      })

    %{organization: organization, site: site}
  end

  describe "get_device_status_counts/1" do
    test "returns empty map when no devices exist", %{organization: organization} do
      assert Devices.get_device_status_counts(organization.id) == %{}
    end

    test "returns correct counts for mixed statuses", %{organization: organization, site: site} do
      # Create devices and set their statuses
      for i <- 1..3 do
        {:ok, device} =
          Devices.create_device(%{
            name: "Up Device #{i}",
            ip_address: "192.168.1.#{i}",
            site_id: site.id,
            organization_id: organization.id
          })

        Devices.update_device_status(device, :up)
      end

      for i <- 1..2 do
        {:ok, device} =
          Devices.create_device(%{
            name: "Down Device #{i}",
            ip_address: "192.168.2.#{i}",
            site_id: site.id,
            organization_id: organization.id
          })

        Devices.update_device_status(device, :down)
      end

      {:ok, _unknown_device} =
        Devices.create_device(%{
          name: "Unknown Device",
          ip_address: "192.168.3.1",
          site_id: site.id,
          organization_id: organization.id
        })

      # Unknown is the default status, so no need to update

      counts = Devices.get_device_status_counts(organization.id)

      assert counts == %{up: 3, down: 2, unknown: 1}
    end

    test "only counts devices for the given organization", %{organization: organization, site: site} do
      # Create device in our org
      {:ok, device} =
        Devices.create_device(%{
          name: "Our Device",
          ip_address: "192.168.1.1",
          site_id: site.id,
          organization_id: organization.id
        })

      Devices.update_device_status(device, :up)

      # Create device in a different org
      other_user = user_fixture()
      {:ok, other_org} = Towerops.Organizations.create_organization(%{name: "Other Org"}, other_user.id)

      {:ok, other_site} =
        Towerops.Sites.create_site(%{
          name: "Other Site",
          organization_id: other_org.id
        })

      {:ok, other_device} =
        Devices.create_device(%{
          name: "Other Device",
          ip_address: "192.168.1.1",
          site_id: other_site.id,
          organization_id: other_org.id
        })

      Devices.update_device_status(other_device, :down)

      # Our org should only see its own device
      counts = Devices.get_device_status_counts(organization.id)
      assert counts == %{up: 1}

      # Other org should only see its own device
      other_counts = Devices.get_device_status_counts(other_org.id)
      assert other_counts == %{down: 1}
    end

    test "returns correct counts after status changes", %{organization: organization, site: site} do
      {:ok, device} =
        Devices.create_device(%{
          name: "Device",
          ip_address: "192.168.1.1",
          site_id: site.id,
          organization_id: organization.id
        })

      # Initially unknown
      assert Devices.get_device_status_counts(organization.id) == %{unknown: 1}

      # Change to up
      {:ok, device} = Devices.update_device_status(device, :up)
      assert Devices.get_device_status_counts(organization.id) == %{up: 1}

      # Change to down
      {:ok, _device} = Devices.update_device_status(device, :down)
      assert Devices.get_device_status_counts(organization.id) == %{down: 1}
    end
  end
end
