defmodule Towerops.Snmp.Profiles.Vendors.Registry do
  @moduledoc """
  Registry for vendor-specific SNMP modules.

  Maps profile names to their vendor module implementations,
  similar to how LibreNMS maps OS names to PHP classes.
  """

  alias Towerops.Snmp.Client
  alias Towerops.Snmp.Profiles.Vendors.Adtran
  alias Towerops.Snmp.Profiles.Vendors.Adva
  alias Towerops.Snmp.Profiles.Vendors.Aerohive
  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.Aruba
  alias Towerops.Snmp.Profiles.Vendors.Aviat
  alias Towerops.Snmp.Profiles.Vendors.Baicells
  alias Towerops.Snmp.Profiles.Vendors.Brocade
  alias Towerops.Snmp.Profiles.Vendors.Calix
  alias Towerops.Snmp.Profiles.Vendors.CambiumPtp
  alias Towerops.Snmp.Profiles.Vendors.Ceragon
  alias Towerops.Snmp.Profiles.Vendors.Cisco
  alias Towerops.Snmp.Profiles.Vendors.Ciscowap
  alias Towerops.Snmp.Profiles.Vendors.Ciscowlc
  alias Towerops.Snmp.Profiles.Vendors.Cmm
  alias Towerops.Snmp.Profiles.Vendors.Cnmatrix
  alias Towerops.Snmp.Profiles.Vendors.Cnpilot
  alias Towerops.Snmp.Profiles.Vendors.Cnwave60
  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.Edgeswitch
  alias Towerops.Snmp.Profiles.Vendors.Engenius
  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.Grandstream
  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.Netonix
  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.Powervault
  alias Towerops.Snmp.Profiles.Vendors.Proxim
  alias Towerops.Snmp.Profiles.Vendors.Racom
  alias Towerops.Snmp.Profiles.Vendors.Radwin
  alias Towerops.Snmp.Profiles.Vendors.Riverbed
  alias Towerops.Snmp.Profiles.Vendors.Routeros
  alias Towerops.Snmp.Profiles.Vendors.Ruckus
  alias Towerops.Snmp.Profiles.Vendors.RuckusSz
  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.Sub10
  alias Towerops.Snmp.Profiles.Vendors.Teltonika
  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

  @vendors [
    Adtran,
    Adva,
    Aerohive,
    Airfiber,
    Airos,
    AlliedTelesis,
    Altalabs,
    Alvarion,
    Apc,
    Arista,
    Aruba,
    Aviat,
    Baicells,
    Brocade,
    Calix,
    CambiumPtp,
    Ceragon,
    Cisco,
    Ciscowap,
    Ciscowlc,
    Cmm,
    Cnmatrix,
    Cnpilot,
    Cnwave60,
    Cyberpower,
    Deliberant,
    Dell,
    Dlink,
    Dlinkap,
    Dragonwave,
    Eaton,
    Edgeswitch,
    Engenius,
    Epmp,
    Exalt,
    F5,
    Fortiap,
    Fortinet,
    Fortiwlc,
    Grandstream,
    Hp,
    Huawei,
    Juniper,
    Liebert,
    Ligoos,
    Meraki,
    Mikrotik,
    Mimosa,
    MoxaAwk,
    Netgear,
    Netonix,
    Nokia,
    Omnitron,
    Paloalto,
    Pepwave,
    Pmp,
    Powervault,
    Proxim,
    Racom,
    Radwin,
    Riverbed,
    Routeros,
    Ruckus,
    RuckusSz,
    Saf,
    Siae,
    Siklu,
    Sonicwall,
    Stellar,
    Sub10,
    Teltonika,
    Tplink,
    Tranzeo,
    Tripplite,
    Unifi,
    Ups,
    Vertiv,
    Xirrus,
    Zyxel,
    ZyxelWlc
  ]

  @doc """
  Get the vendor module for a given profile name.
  Returns nil if no vendor-specific module exists.
  """
  @spec get_vendor(String.t()) :: module() | nil
  def get_vendor(profile_name) do
    Enum.find(@vendors, fn vendor ->
      profile_name in vendor.profile_names()
    end)
  end

  @doc """
  List all registered vendor modules.
  """
  @spec list_vendors() :: [module()]
  def list_vendors, do: @vendors

  @doc """
  List all profile names handled by vendor modules.
  """
  @spec list_profile_names() :: [String.t()]
  def list_profile_names do
    Enum.flat_map(@vendors, & &1.profile_names())
  end

  @doc """
  Detect hardware using the appropriate vendor module.
  Returns nil if no vendor module matches or detection fails.
  """
  @spec detect_hardware(String.t(), Client.connection_opts()) :: String.t() | nil
  def detect_hardware(profile_name, client_opts) do
    case get_vendor(profile_name) do
      nil -> nil
      vendor -> vendor.detect_hardware(client_opts)
    end
  end

  @doc """
  Discover wireless sensors using the appropriate vendor module.
  Returns empty list if no vendor module matches.
  """
  @spec discover_wireless_sensors(String.t(), Client.connection_opts()) :: [map()]
  def discover_wireless_sensors(profile_name, client_opts) do
    case get_vendor(profile_name) do
      nil -> []
      vendor -> vendor.discover_wireless_sensors(client_opts)
    end
  end

  @doc """
  Get wireless OID definitions for debug data collection.
  Returns empty list if no vendor module matches.
  """
  @spec get_wireless_oid_defs(String.t()) :: [map()]
  def get_wireless_oid_defs(profile_name) do
    case get_vendor(profile_name) do
      nil -> []
      vendor -> vendor.wireless_oid_defs()
    end
  end
end
