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

  import Mox

  alias Towerops.Snmp.Profiles.Vendors.Ciscowap
  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 ciscowap profile name" do
      assert Ciscowap.profile_names() == ["ciscowap"]
    end
  end

  describe "detect_hardware/1" do
    test "detects hardware from model OID" do
      expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.9.9.618.1.1.1.0", _ ->
        {:ok, "WAP371"}
      end)

      assert Ciscowap.detect_hardware(@client_opts) == "WAP371"
    end

    test "returns nil when OID unavailable" do
      expect(SnmpMock, :get, fn _, _, _ ->
        {:error, :no_such_object}
      end)

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

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

      assert is_list(defs)
      assert [_ | _] = defs
    end

    test "includes client count sensor" do
      defs = Ciscowap.wireless_oid_defs()
      clients = Enum.find(defs, &(&1.sensor_descr == "Associated Clients"))

      assert clients
      assert clients.sensor_type == "clients"
    end

    test "includes channel utilization sensors" do
      defs = Ciscowap.wireless_oid_defs()
      util_2g = Enum.find(defs, &(&1.sensor_descr == "2.4GHz Channel Utilization"))
      util_5g = Enum.find(defs, &(&1.sensor_descr == "5GHz Channel Utilization"))

      assert util_2g
      assert util_2g.sensor_type == "load"
      assert util_2g.sensor_unit == "%"
      assert util_5g
      assert util_5g.sensor_type == "load"
    end

    test "includes noise floor sensors" do
      defs = Ciscowap.wireless_oid_defs()
      noise_2g = Enum.find(defs, &(&1.sensor_descr == "2.4GHz Noise Floor"))
      noise_5g = Enum.find(defs, &(&1.sensor_descr == "5GHz Noise Floor"))

      assert noise_2g
      assert noise_2g.sensor_type == "noise"
      assert noise_2g.sensor_unit == "dBm"
      assert noise_5g
      assert noise_5g.sensor_type == "noise"
    end
  end

  describe "discover_wireless_sensors/1" do
    test "discovers sensors when SNMP responds" do
      expect(SnmpMock, :get, 5, fn _, oid, _ ->
        cond do
          String.contains?(oid, "9.9.618.1.8.1.0") -> {:ok, 28}
          String.contains?(oid, "9.9.618.1.4.1.1.8.1") -> {:ok, 45}
          String.contains?(oid, "9.9.618.1.4.1.1.8.2") -> {:ok, 30}
          String.contains?(oid, "9.9.618.1.4.1.1.5.1") -> {:ok, -95}
          String.contains?(oid, "9.9.618.1.4.1.1.5.2") -> {:ok, -92}
          true -> {:error, :no_such_object}
        end
      end)

      sensors = Ciscowap.discover_wireless_sensors(@client_opts)

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

    test "returns empty list when no sensors respond" do
      expect(SnmpMock, :get, 5, fn _, _, _ ->
        {:error, :no_such_object}
      end)

      sensors = Ciscowap.discover_wireless_sensors(@client_opts)

      assert sensors == []
    end
  end
end
