defmodule Towerops.Alerts.Alert do
  @moduledoc """
  Alert schema for device monitoring alerts.

  Tracks device_up, device_down, and sensor threshold alerts with
  acknowledgement status and auto-resolution.
  """
  use Ecto.Schema

  import Ecto.Changeset

  alias Ecto.Association.NotLoaded
  alias Towerops.Accounts.User
  alias Towerops.Devices.Device

  @primary_key {:id, :binary_id, autogenerate: true}
  @foreign_key_type :binary_id
  schema "alerts" do
    field :alert_type, Ecto.Enum, values: [:device_down, :device_up]
    field :triggered_at, :utc_datetime
    field :acknowledged_at, :utc_datetime
    field :resolved_at, :utc_datetime
    field :email_sent_at, :utc_datetime
    field :message, :string
    field :gaiia_impact, :map

    belongs_to :device, Device
    belongs_to :acknowledged_by, User

    timestamps(type: :utc_datetime)
  end

  @type t :: %__MODULE__{
          id: Ecto.UUID.t(),
          alert_type: :device_down | :device_up,
          triggered_at: DateTime.t(),
          acknowledged_at: DateTime.t() | nil,
          resolved_at: DateTime.t() | nil,
          email_sent_at: DateTime.t() | nil,
          message: String.t() | nil,
          gaiia_impact: map() | nil,
          device_id: Ecto.UUID.t(),
          device: NotLoaded.t() | Device.t(),
          acknowledged_by_id: Ecto.UUID.t() | nil,
          acknowledged_by: NotLoaded.t() | User.t() | nil,
          inserted_at: DateTime.t(),
          updated_at: DateTime.t()
        }

  @doc false
  def changeset(alert, attrs) do
    alert
    |> cast(attrs, [
      :device_id,
      :alert_type,
      :triggered_at,
      :acknowledged_at,
      :acknowledged_by_id,
      :resolved_at,
      :email_sent_at,
      :message,
      :gaiia_impact
    ])
    |> validate_required([:device_id, :alert_type, :triggered_at])
    |> foreign_key_constraint(:device_id)
    |> foreign_key_constraint(:acknowledged_by_id)
  end
end
