defmodule Towerops.Snmp.Sensor do
  @moduledoc """
  SNMP sensor schema for monitoring environmental sensors.

  Tracks temperature, fan speed, voltage, power, and other sensors
  discovered via ENTITY-SENSOR-MIB or vendor-specific MIBs.
  """
  use Ecto.Schema

  import Ecto.Changeset

  alias Ecto.Association.NotLoaded
  alias Towerops.Snmp.Device
  alias Towerops.Snmp.SensorReading

  @primary_key {:id, :binary_id, autogenerate: true}
  @foreign_key_type :binary_id
  schema "snmp_sensors" do
    field :sensor_type, :string
    field :sensor_index, :string
    field :sensor_oid, :string
    field :sensor_descr, :string
    field :sensor_unit, :string
    field :sensor_divisor, :integer, default: 1
    field :monitored, :boolean, default: true
    field :last_value, :float
    field :last_checked_at, :utc_datetime
    field :metadata, :map, default: %{}

    belongs_to :snmp_device, Device

    has_many :readings, SensorReading, foreign_key: :sensor_id

    timestamps(type: :utc_datetime)
  end

  @type t :: %__MODULE__{
          id: Ecto.UUID.t(),
          sensor_type: String.t(),
          sensor_index: String.t(),
          sensor_oid: String.t(),
          sensor_descr: String.t(),
          sensor_unit: String.t(),
          sensor_divisor: integer(),
          monitored: boolean(),
          last_value: float() | nil,
          last_checked_at: DateTime.t() | nil,
          metadata: map(),
          snmp_device_id: Ecto.UUID.t(),
          snmp_device: NotLoaded.t() | Device.t(),
          readings: NotLoaded.t() | [SensorReading.t()],
          inserted_at: DateTime.t(),
          updated_at: DateTime.t()
        }

  @doc false
  def changeset(sensor, attrs) do
    sensor
    |> cast(attrs, [
      :snmp_device_id,
      :sensor_type,
      :sensor_index,
      :sensor_oid,
      :sensor_descr,
      :sensor_unit,
      :sensor_divisor,
      :monitored,
      :last_value,
      :last_checked_at,
      :metadata
    ])
    |> validate_required([:snmp_device_id, :sensor_type, :sensor_index, :sensor_oid])
    |> unique_constraint([:snmp_device_id, :sensor_index])
    |> foreign_key_constraint(:snmp_device_id)
  end
end
