defmodule Towerops.Workers.DeviceHealthInsightWorker do
  @moduledoc """
  Oban cron worker that generates SNMP-based health insights.

  Runs nightly to detect:
  - `device_poll_gap`: Devices not polled in over 24 hours
  """
  use Oban.Worker, queue: :maintenance

  import Ecto.Query

  alias Towerops.Devices.Device
  alias Towerops.Preseem.Insights
  alias Towerops.Repo

  @poll_gap_hours 24

  @impl Oban.Worker
  def perform(%Oban.Job{}) do
    devices = list_stale_monitored_devices()

    Enum.each(devices, &generate_poll_gap_insight/1)

    :ok
  end

  defp list_stale_monitored_devices do
    cutoff = DateTime.add(DateTime.utc_now(), -@poll_gap_hours, :hour)

    Device
    |> where([d], d.monitoring_enabled == true)
    |> where([d], not is_nil(d.last_snmp_poll_at))
    |> where([d], d.last_snmp_poll_at < ^cutoff)
    |> Repo.all()
  end

  defp generate_poll_gap_insight(device) do
    hours_ago = DateTime.diff(DateTime.utc_now(), device.last_snmp_poll_at, :hour)

    Insights.insert_insight_if_new(%{
      organization_id: device.organization_id,
      device_id: device.id,
      type: "device_poll_gap",
      urgency: "warning",
      channel: "proactive",
      source: "snmp",
      title: "#{device.name} has not been polled in #{hours_ago} hours",
      description:
        "Device #{device.name} was last polled #{hours_ago} hours ago. " <>
          "Check SNMP connectivity and agent status.",
      metadata: %{
        "last_poll_at" => DateTime.to_iso8601(device.last_snmp_poll_at),
        "hours_since_poll" => hours_ago
      }
    })
  end
end
