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

  import Mox

  alias Towerops.Snmp.Profiles.Vendors.Adtran
  alias Towerops.Snmp.Profiles.Vendors.Adva
  alias Towerops.Snmp.Profiles.Vendors.Airfiber
  alias Towerops.Snmp.Profiles.Vendors.Airos
  alias Towerops.Snmp.Profiles.Vendors.AlliedTelesis
  alias Towerops.Snmp.Profiles.Vendors.Altalabs
  alias Towerops.Snmp.Profiles.Vendors.Alvarion
  alias Towerops.Snmp.Profiles.Vendors.Apc
  alias Towerops.Snmp.Profiles.Vendors.Arista
  alias Towerops.Snmp.Profiles.Vendors.Brocade
  alias Towerops.Snmp.Profiles.Vendors.Calix
  alias Towerops.Snmp.Profiles.Vendors.Ceragon
  alias Towerops.Snmp.Profiles.Vendors.Cisco
  alias Towerops.Snmp.Profiles.Vendors.Cmm
  alias Towerops.Snmp.Profiles.Vendors.Cnpilot
  alias Towerops.Snmp.Profiles.Vendors.Cyberpower
  alias Towerops.Snmp.Profiles.Vendors.Deliberant
  alias Towerops.Snmp.Profiles.Vendors.Dell
  alias Towerops.Snmp.Profiles.Vendors.Dlink
  alias Towerops.Snmp.Profiles.Vendors.Dlinkap
  alias Towerops.Snmp.Profiles.Vendors.Dragonwave
  alias Towerops.Snmp.Profiles.Vendors.Eaton
  alias Towerops.Snmp.Profiles.Vendors.Epmp
  alias Towerops.Snmp.Profiles.Vendors.Exalt
  alias Towerops.Snmp.Profiles.Vendors.F5
  alias Towerops.Snmp.Profiles.Vendors.Fortiap
  alias Towerops.Snmp.Profiles.Vendors.Fortinet
  alias Towerops.Snmp.Profiles.Vendors.Fortiwlc
  alias Towerops.Snmp.Profiles.Vendors.Hp
  alias Towerops.Snmp.Profiles.Vendors.Huawei
  alias Towerops.Snmp.Profiles.Vendors.Juniper
  alias Towerops.Snmp.Profiles.Vendors.Liebert
  alias Towerops.Snmp.Profiles.Vendors.Ligoos
  alias Towerops.Snmp.Profiles.Vendors.Meraki
  alias Towerops.Snmp.Profiles.Vendors.Mikrotik
  alias Towerops.Snmp.Profiles.Vendors.Mimosa
  alias Towerops.Snmp.Profiles.Vendors.MoxaAwk
  alias Towerops.Snmp.Profiles.Vendors.Netgear
  alias Towerops.Snmp.Profiles.Vendors.Nokia
  alias Towerops.Snmp.Profiles.Vendors.Omnitron
  alias Towerops.Snmp.Profiles.Vendors.Paloalto
  alias Towerops.Snmp.Profiles.Vendors.Pepwave
  alias Towerops.Snmp.Profiles.Vendors.Pmp
  alias Towerops.Snmp.Profiles.Vendors.Proxim
  alias Towerops.Snmp.Profiles.Vendors.Racom
  alias Towerops.Snmp.Profiles.Vendors.Radwin
  alias Towerops.Snmp.Profiles.Vendors.Registry
  alias Towerops.Snmp.Profiles.Vendors.Riverbed
  alias Towerops.Snmp.Profiles.Vendors.Routeros
  alias Towerops.Snmp.Profiles.Vendors.Ruckus
  alias Towerops.Snmp.Profiles.Vendors.Saf
  alias Towerops.Snmp.Profiles.Vendors.Siae
  alias Towerops.Snmp.Profiles.Vendors.Siklu
  alias Towerops.Snmp.Profiles.Vendors.Sonicwall
  alias Towerops.Snmp.Profiles.Vendors.Stellar
  alias Towerops.Snmp.Profiles.Vendors.Tplink
  alias Towerops.Snmp.Profiles.Vendors.Tranzeo
  alias Towerops.Snmp.Profiles.Vendors.Tripplite
  alias Towerops.Snmp.Profiles.Vendors.Unifi
  alias Towerops.Snmp.Profiles.Vendors.Ups
  alias Towerops.Snmp.Profiles.Vendors.Vertiv
  alias Towerops.Snmp.Profiles.Vendors.Xirrus
  alias Towerops.Snmp.Profiles.Vendors.Zyxel
  alias Towerops.Snmp.Profiles.Vendors.ZyxelWlc
  alias Towerops.Snmp.SnmpMock

  setup :verify_on_exit!

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

  describe "list_vendors/0" do
    test "returns all registered vendor modules" do
      vendors = Registry.list_vendors()

      assert is_list(vendors)
      assert Epmp in vendors
      assert Airos in vendors
      assert Airfiber in vendors
      assert Routeros in vendors
      assert Pmp in vendors
      assert Mimosa in vendors
      assert Siklu in vendors
      assert Radwin in vendors
      assert Unifi in vendors
      assert Ligoos in vendors
      assert Cnpilot in vendors
      assert Saf in vendors
      assert Ruckus in vendors
      assert Dragonwave in vendors
      assert Racom in vendors
      assert Exalt in vendors
      assert Siae in vendors
      assert Altalabs in vendors
      assert Alvarion in vendors
      assert Proxim in vendors
      assert Stellar in vendors
      assert Xirrus in vendors
      assert ZyxelWlc in vendors
      assert Dlinkap in vendors
      assert Fortiap in vendors
      assert MoxaAwk in vendors
      assert Ceragon in vendors
      assert Cmm in vendors
      assert Pepwave in vendors
      assert Tranzeo in vendors
      assert Fortiwlc in vendors
      assert Meraki in vendors
      assert Apc in vendors
      assert Arista in vendors
      assert Calix in vendors
      assert Adtran in vendors
      assert AlliedTelesis in vendors
      # New auto-generated vendors
      assert Cisco in vendors
      assert Juniper in vendors
      assert Hp in vendors
      assert Dell in vendors
      assert Fortinet in vendors
      assert Huawei in vendors
      assert Nokia in vendors
      assert Omnitron in vendors
      assert Paloalto in vendors
      assert F5 in vendors
      assert Brocade in vendors
      assert Netgear in vendors
      assert Dlink in vendors
      assert Tplink in vendors
      assert Zyxel in vendors
      assert Cyberpower in vendors
      assert Eaton in vendors
      assert Liebert in vendors
      assert Tripplite in vendors
      assert Ups in vendors
      assert Vertiv in vendors
      assert Riverbed in vendors
      assert Sonicwall in vendors
      assert Mikrotik in vendors
      assert Adva in vendors
    end
  end

  describe "list_profile_names/0" do
    test "returns all profile names from all vendors" do
      names = Registry.list_profile_names()

      assert is_list(names)
      # Check for some known profile names
      assert "epmp" in names
      assert "airos" in names
      assert "airos-af" in names
      assert "routeros" in names
      assert "pmp" in names
      assert "mimosa" in names
      assert "siklu" in names
      assert "radwin" in names
      assert "unifi" in names
      assert "ligoos" in names
      assert "deliberant" in names
      assert "cnpilot" in names
      assert "saf" in names
      assert "ruckuswireless" in names
      assert "horizon-compact" in names
      assert "ray" in names
      assert "extendair" in names
      assert "alfo80hd" in names
      assert "altalabs" in names
      assert "breeze" in names
      assert "proxim" in names
      assert "stellar" in names
      assert "xirrus_aos" in names
      assert "zyxelwlc" in names
      assert "dlinkap" in names
      assert "fortiap" in names
      assert "moxa-awk" in names
      assert "ceraos" in names
      assert "cmm" in names
      assert "pepwave" in names
      assert "tranzeo" in names
      assert "fortiwlc" in names
      assert "merakimr" in names
      assert "merakims" in names
      assert "merakimx" in names
      assert "cnpilotr" in names
      assert "apc" in names
      assert "aos-emu2" in names
      assert "aos" in names
      assert "aos6" in names
      assert "aos7" in names
      assert "omnitron-iconverter" in names
      assert "arista_eos" in names
      assert "calix" in names
      assert "adtran-aos" in names
      assert "allied" in names
      assert "awplus" in names
    end
  end

  describe "get_vendor/1" do
    test "returns Epmp for epmp profile" do
      assert Registry.get_vendor("epmp") == Epmp
    end

    test "returns Airos for airos profile" do
      assert Registry.get_vendor("airos") == Airos
    end

    test "returns Routeros for routeros profile" do
      assert Registry.get_vendor("routeros") == Routeros
    end

    test "returns Pmp for pmp profile" do
      assert Registry.get_vendor("pmp") == Pmp
    end

    test "returns Mimosa for mimosa profile" do
      assert Registry.get_vendor("mimosa") == Mimosa
    end

    test "returns Siklu for siklu profile" do
      assert Registry.get_vendor("siklu") == Siklu
    end

    test "returns Radwin for radwin profile" do
      assert Registry.get_vendor("radwin") == Radwin
    end

    test "returns Unifi for unifi profile" do
      assert Registry.get_vendor("unifi") == Unifi
    end

    test "returns Ligoos for ligoos profile" do
      assert Registry.get_vendor("ligoos") == Ligoos
    end

    test "returns Deliberant for deliberant profile" do
      assert Registry.get_vendor("deliberant") == Deliberant
    end

    test "returns Cnpilot for cnpilot profile" do
      assert Registry.get_vendor("cnpilot") == Cnpilot
    end

    test "returns Saf for saf profile" do
      assert Registry.get_vendor("saf") == Saf
    end

    test "returns Ruckus for ruckuswireless profile" do
      assert Registry.get_vendor("ruckuswireless") == Ruckus
    end

    test "returns Dragonwave for horizon-compact profile" do
      assert Registry.get_vendor("horizon-compact") == Dragonwave
    end

    test "returns Airfiber for airos-af profile" do
      assert Registry.get_vendor("airos-af") == Airfiber
    end

    test "returns Racom for ray profile" do
      assert Registry.get_vendor("ray") == Racom
    end

    test "returns Exalt for extendair profile" do
      assert Registry.get_vendor("extendair") == Exalt
    end

    test "returns Siae for alfo80hd profile" do
      assert Registry.get_vendor("alfo80hd") == Siae
    end

    test "returns Altalabs for altalabs profile" do
      assert Registry.get_vendor("altalabs") == Altalabs
    end

    test "returns Alvarion for breeze profile" do
      assert Registry.get_vendor("breeze") == Alvarion
    end

    test "returns Proxim for proxim profile" do
      assert Registry.get_vendor("proxim") == Proxim
    end

    test "returns Stellar for stellar profile" do
      assert Registry.get_vendor("stellar") == Stellar
    end

    test "returns Xirrus for xirrus_aos profile" do
      assert Registry.get_vendor("xirrus_aos") == Xirrus
    end

    test "returns ZyxelWlc for zyxelwlc profile" do
      assert Registry.get_vendor("zyxelwlc") == ZyxelWlc
    end

    test "returns Dlinkap for dlinkap profile" do
      assert Registry.get_vendor("dlinkap") == Dlinkap
    end

    test "returns Fortiap for fortiap profile" do
      assert Registry.get_vendor("fortiap") == Fortiap
    end

    test "returns MoxaAwk for moxa-awk profile" do
      assert Registry.get_vendor("moxa-awk") == MoxaAwk
    end

    test "returns Ceragon for ceraos profile" do
      assert Registry.get_vendor("ceraos") == Ceragon
    end

    test "returns Cmm for cmm profile" do
      assert Registry.get_vendor("cmm") == Cmm
    end

    test "returns Pepwave for pepwave profile" do
      assert Registry.get_vendor("pepwave") == Pepwave
    end

    test "returns Tranzeo for tranzeo profile" do
      assert Registry.get_vendor("tranzeo") == Tranzeo
    end

    test "returns Fortiwlc for fortiwlc profile" do
      assert Registry.get_vendor("fortiwlc") == Fortiwlc
    end

    test "returns Meraki for merakimr profile" do
      assert Registry.get_vendor("merakimr") == Meraki
    end

    test "returns Meraki for merakims profile" do
      assert Registry.get_vendor("merakims") == Meraki
    end

    test "returns Meraki for merakimx profile" do
      assert Registry.get_vendor("merakimx") == Meraki
    end

    test "returns Apc for apc profile" do
      assert Registry.get_vendor("apc") == Apc
    end

    test "returns Apc for aos-emu2 profile" do
      assert Registry.get_vendor("aos-emu2") == Apc
    end

    test "returns Nokia for aos profile" do
      assert Registry.get_vendor("aos") == Nokia
    end

    test "returns Nokia for aos6 profile" do
      assert Registry.get_vendor("aos6") == Nokia
    end

    test "returns Nokia for aos7 profile" do
      assert Registry.get_vendor("aos7") == Nokia
    end

    test "returns Omnitron for omnitron-iconverter profile" do
      assert Registry.get_vendor("omnitron-iconverter") == Omnitron
    end

    test "returns Arista for arista_eos profile" do
      assert Registry.get_vendor("arista_eos") == Arista
    end

    test "returns Calix for calix profile" do
      assert Registry.get_vendor("calix") == Calix
    end

    test "returns Adtran for adtran-aos profile" do
      assert Registry.get_vendor("adtran-aos") == Adtran
    end

    test "returns AlliedTelesis for allied profile" do
      assert Registry.get_vendor("allied") == AlliedTelesis
    end

    test "returns AlliedTelesis for awplus profile" do
      assert Registry.get_vendor("awplus") == AlliedTelesis
    end

    test "returns nil for unknown profile" do
      assert Registry.get_vendor("unknown_vendor") == nil
    end
  end

  describe "detect_hardware/2" do
    test "delegates to vendor module" do
      expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.41112.1.6.3.3.0", _ ->
        {:ok, {:octet_string, "UAP-AC-HD"}}
      end)

      assert Registry.detect_hardware("unifi", @client_opts) == "UAP-AC-HD"
    end

    test "returns nil for unknown profile" do
      assert Registry.detect_hardware("unknown", @client_opts) == nil
    end
  end

  describe "discover_wireless_sensors/2" do
    test "delegates to vendor module" do
      expect(SnmpMock, :get, 4, fn _, oid, _ ->
        cond do
          String.contains?(oid, "17713.22.1.1.1.14.0") -> {:ok, {:integer, 25}}
          String.contains?(oid, "17713.22.1.3.1.11.0") -> {:ok, {:integer, 30}}
          String.contains?(oid, "17713.22.1.2.1.8.0") -> {:ok, {:integer, 20}}
          String.contains?(oid, "17713.22.1.2.1.16.0") -> {:ok, {:integer, -95}}
          true -> {:error, :no_such_object}
        end
      end)

      sensors = Registry.discover_wireless_sensors("cnpilot", @client_opts)

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

    test "returns empty list for unknown profile" do
      assert Registry.discover_wireless_sensors("unknown", @client_opts) == []
    end
  end

  describe "get_wireless_oid_defs/1" do
    test "returns OID definitions for known profile" do
      defs = Registry.get_wireless_oid_defs("pmp")

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

    test "returns empty list for unknown profile" do
      assert Registry.get_wireless_oid_defs("unknown") == []
    end
  end
end
