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

  import Mox

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

  describe "detect_hardware/1" do
    test "detects hardware from model OID" do
      expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.46242.1.1.0", _ ->
        {:ok, "WS-12-250-AC"}
      end)

      assert Netonix.detect_hardware(@client_opts) == "WS-12-250-AC"
    end

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

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

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

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

    test "includes board temperature sensor" do
      defs = Netonix.wireless_oid_defs()
      temp = Enum.find(defs, &(&1.sensor_descr == "Board Temperature"))

      assert temp
      assert temp.sensor_type == "temperature"
      assert temp.sensor_unit == "C"
    end

    test "includes CPU temperature sensor" do
      defs = Netonix.wireless_oid_defs()
      temp = Enum.find(defs, &(&1.sensor_descr == "CPU Temperature"))

      assert temp
      assert temp.sensor_type == "temperature"
    end

    test "includes fan speed sensor" do
      defs = Netonix.wireless_oid_defs()
      fan = Enum.find(defs, &(&1.sensor_descr == "Fan Speed"))

      assert fan
      assert fan.sensor_type == "fanspeed"
      assert fan.sensor_unit == "RPM"
    end

    test "includes voltage sensors" do
      defs = Netonix.wireless_oid_defs()
      psu1 = Enum.find(defs, &(&1.sensor_descr == "PSU1 Voltage"))
      psu2 = Enum.find(defs, &(&1.sensor_descr == "PSU2 Voltage"))

      assert psu1
      assert psu1.sensor_type == "voltage"
      assert psu1.sensor_divisor == 1000
      assert psu2
      assert psu2.sensor_type == "voltage"
    end

    test "includes PoE power sensor" do
      defs = Netonix.wireless_oid_defs()
      poe = Enum.find(defs, &(&1.sensor_descr == "Total PoE Power"))

      assert poe
      assert poe.sensor_type == "power"
      assert poe.sensor_unit == "W"
    end
  end

  describe "discover_wireless_sensors/1" do
    test "discovers sensors when SNMP responds" do
      expect(SnmpMock, :get, 6, fn _, oid, _ ->
        cond do
          String.contains?(oid, "46242.2.1.0") -> {:ok, 45}
          String.contains?(oid, "46242.2.2.0") -> {:ok, 55}
          String.contains?(oid, "46242.2.3.0") -> {:ok, 3500}
          String.contains?(oid, "46242.3.1.0") -> {:ok, 54_000}
          String.contains?(oid, "46242.3.2.0") -> {:ok, 48_000}
          String.contains?(oid, "46242.4.1.0") -> {:ok, 75_000}
          true -> {:error, :no_such_object}
        end
      end)

      sensors = Netonix.discover_wireless_sensors(@client_opts)

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

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

      sensors = Netonix.discover_wireless_sensors(@client_opts)

      assert sensors == []
    end
  end
end
