defmodule Towerops.Snmp.Profiles.Vendors.AirosTest do
  use Towerops.DataCase, async: true

  import Mox

  alias Towerops.Snmp.Profiles.Vendors.Airos
  alias Towerops.Snmp.SnmpMock

  setup :verify_on_exit!

  @client_opts [
    ip: "192.168.1.1",
    community: "public",
    version: "2c",
    port: 161,
    timeout: 5000
  ]

  describe "profile_names/0" do
    test "returns expected profile names" do
      assert Airos.profile_names() == ["airos"]
    end
  end

  describe "detect_hardware/1" do
    test "returns product name when SNMP responds" do
      expect(SnmpMock, :get_next, fn _, "1.2.840.10036.3.1.2.1.3", _ ->
        {:ok, %{oid: "1.2.840.10036.3.1.2.1.3.0", value: "LiteBeam 5AC Gen2"}}
      end)

      assert Airos.detect_hardware(@client_opts) == "LiteBeam 5AC Gen2"
    end

    test "returns nil when SNMP fails" do
      expect(SnmpMock, :get_next, fn _, _, _ ->
        {:error, :timeout}
      end)

      assert Airos.detect_hardware(@client_opts) == nil
    end

    test "returns nil when response is not a string" do
      expect(SnmpMock, :get_next, fn _, "1.2.840.10036.3.1.2.1.3", _ ->
        {:ok, %{oid: "1.2.840.10036.3.1.2.1.3.0", value: 12_345}}
      end)

      assert Airos.detect_hardware(@client_opts) == nil
    end
  end

  describe "wireless_oid_defs/0" do
    test "returns list of sensor definitions" do
      defs = Airos.wireless_oid_defs()

      assert is_list(defs)
      assert length(defs) >= 10
    end

    test "each definition has required fields" do
      defs = Airos.wireless_oid_defs()

      Enum.each(defs, fn def ->
        assert Map.has_key?(def, :oid)
        assert Map.has_key?(def, :sensor_descr)
        assert Map.has_key?(def, :sensor_type)
        assert Map.has_key?(def, :sensor_unit)
        assert Map.has_key?(def, :sensor_divisor)
      end)
    end

    test "includes frequency sensor" do
      defs = Airos.wireless_oid_defs()
      freq = Enum.find(defs, &(&1.sensor_descr == "Frequency"))

      assert freq
      assert freq.sensor_type == "frequency"
      assert freq.sensor_unit == "MHz"
    end

    test "includes CCQ sensor" do
      defs = Airos.wireless_oid_defs()
      ccq = Enum.find(defs, &(&1.sensor_descr == "CCQ"))

      assert ccq
      assert ccq.sensor_type == "ccq"
      assert ccq.sensor_unit == "%"
    end
  end

  describe "discover_wireless_sensors/1" do
    test "discovers sensors when SNMP responds" do
      defs = Airos.wireless_oid_defs()
      num_defs = length(defs)

      expect(SnmpMock, :get, num_defs, fn _, _oid, _ ->
        {:ok, 42}
      end)

      sensors = Airos.discover_wireless_sensors(@client_opts)

      assert is_list(sensors)
      assert length(sensors) == num_defs
    end

    test "returns empty list when no sensors respond" do
      defs = Airos.wireless_oid_defs()
      num_defs = length(defs)

      expect(SnmpMock, :get, num_defs, fn _, _, _ ->
        {:error, :no_such_object}
      end)

      sensors = Airos.discover_wireless_sensors(@client_opts)

      assert sensors == []
    end
  end
end
