defmodule Towerops.Snmp.Profiles.Ubiquiti do
  @moduledoc """
  SNMP profile for Ubiquiti devices (AirFiber, AirMax, etc.) using Ubiquiti airOS MIB.

  Discovers wireless-specific sensors:
  - TX/RX Frequency
  - TX/RX Throughput
  - TX/RX Capacity
  - Signal Strength
  - Remote device information
  """

  alias Towerops.Snmp.Client
  alias Towerops.Snmp.Profiles.Base

  require Logger

  # Ubiquiti enterprise MIB base: 1.3.6.1.4.1.41112
  @ubnt_base "1.3.6.1.4.1.41112"

  # Radio configuration OIDs (.1.3.1.1)
  @radio_config_base "#{@ubnt_base}.1.3.1.1"
  @radio_tx_freq "#{@radio_config_base}.5"
  @radio_rx_freq "#{@radio_config_base}.6"
  @radio_tx_power "#{@radio_config_base}.9"

  # Radio statistics OIDs (.1.3.2.1)
  @radio_stats_base "#{@ubnt_base}.1.3.2.1"
  @radio_tx_throughput "#{@radio_stats_base}.3"
  @radio_rx_throughput "#{@radio_stats_base}.4"
  @radio_tx_capacity_bps "#{@radio_stats_base}.5"
  @radio_rx_capacity_bps "#{@radio_stats_base}.6"
  @radio_tx_signal "#{@radio_stats_base}.7"
  @radio_rx_signal "#{@radio_stats_base}.8"
  @radio_remote_tx_power "#{@radio_stats_base}.11"
  @radio_remote_rx_power "#{@radio_stats_base}.14"

  @doc """
  Discovers system information using base profile.
  """
  def discover_system_info(client_opts) do
    Base.discover_system_info(client_opts)
  end

  @doc """
  Discovers interfaces using base profile.
  """
  def discover_interfaces(client_opts) do
    Base.discover_interfaces(client_opts)
  end

  @doc """
  Discovers Ubiquiti wireless sensors.
  Includes frequency, throughput, capacity, and signal strength metrics.
  """
  def discover_sensors(client_opts) do
    # Walk the radio config base to see if this is a radio device
    case Client.walk(client_opts, @radio_config_base) do
      {:ok, config} when map_size(config) > 0 ->
        # This is a Ubiquiti radio device, discover wireless sensors
        Logger.debug("Discovered Ubiquiti radio device")
        sensors = discover_radio_sensors(client_opts)
        {:ok, sensors}

      _ ->
        # Not a radio device or no radio data, fall back to base
        Logger.debug("No Ubiquiti radio sensors found, using base profile")
        Base.discover_sensors(client_opts)
    end
  end

  @doc """
  Identifies Ubiquiti device from sysDescr.
  """
  def identify_device(system_info) do
    sys_descr = Map.get(system_info, :sys_descr, "")

    # Extract airOS version if present
    firmware = extract_airos_version(sys_descr)

    Map.merge(system_info, %{
      manufacturer: "Ubiquiti",
      model: detect_model(sys_descr),
      firmware_version: firmware
    })
  end

  # Private functions

  defp discover_radio_sensors(client_opts) do
    # Discover radio index (usually 1 for most devices)
    case Client.walk(client_opts, @radio_config_base) do
      {:ok, entries} when map_size(entries) > 0 ->
        # Extract radio index from first entry
        {first_oid, _} = Enum.at(entries, 0)
        index = extract_radio_index(first_oid)

        build_radio_sensors(client_opts, index)

      _ ->
        []
    end
  end

  defp build_radio_sensors(client_opts, index) do
    Enum.reject(
      [
        build_sensor(client_opts, "#{@radio_tx_freq}.#{index}", "tx_frequency", "TX Frequency", "MHz", 1),
        build_sensor(client_opts, "#{@radio_rx_freq}.#{index}", "rx_frequency", "RX Frequency", "MHz", 1),
        build_sensor(client_opts, "#{@radio_tx_throughput}.#{index}", "tx_throughput", "TX Throughput", "kbps", 1),
        build_sensor(client_opts, "#{@radio_rx_throughput}.#{index}", "rx_throughput", "RX Throughput", "kbps", 1),
        build_sensor(client_opts, "#{@radio_tx_capacity_bps}.#{index}", "tx_capacity", "TX Capacity", "bps", 1),
        build_sensor(client_opts, "#{@radio_rx_capacity_bps}.#{index}", "rx_capacity", "RX Capacity", "bps", 1),
        build_sensor(client_opts, "#{@radio_tx_signal}.#{index}", "tx_signal", "TX Signal", "dBm", 1),
        build_sensor(client_opts, "#{@radio_rx_signal}.#{index}", "rx_signal", "RX Signal", "dBm", 1),
        build_sensor(client_opts, "#{@radio_remote_tx_power}.#{index}", "remote_tx_power", "Remote TX Power", "dBm", 1),
        build_sensor(client_opts, "#{@radio_remote_rx_power}.#{index}", "remote_rx_power", "Remote RX Power", "dBm", 1),
        build_sensor(client_opts, "#{@radio_tx_power}.#{index}", "tx_power", "TX Power", "dBm", 1)
      ],
      &is_nil/1
    )

    # Frequency sensors

    # Throughput sensors (kbps)

    # Capacity sensors (bps)

    # Signal strength sensors

    # Remote power sensors

    # TX Power from config
  end

  defp build_sensor(_client_opts, oid, type, descr, unit, divisor) do
    %{
      sensor_type: type,
      sensor_index: oid,
      sensor_oid: oid,
      sensor_descr: descr,
      sensor_unit: unit,
      sensor_divisor: divisor
    }
  end

  defp extract_radio_index(oid) do
    # OID format: 1.3.6.1.4.1.41112.1.3.1.1.X.INDEX
    parts = String.split(oid, ".")
    List.last(parts)
  end

  defp extract_airos_version(sys_descr) do
    # Extract version from something like "Linux 2.6.33 #1 Wed Mar 18 11:38:22 UTC 2020 armv5tejl"
    case Regex.run(~r/Linux (\d+\.\d+\.\d+)/, sys_descr) do
      [_, version] -> version
      _ -> nil
    end
  end

  defp detect_model(sys_descr) do
    cond do
      String.contains?(sys_descr, "AirFiber") -> "AirFiber"
      String.contains?(sys_descr, "airMAX") -> "airMAX"
      String.contains?(sys_descr, "airOS") -> "airOS Device"
      true -> "Ubiquiti Device"
    end
  end
end
