defmodule Microwaveprop.Workers.PropagationGridWorker do
  @moduledoc """
  Hourly seed worker for the Rust `prop-grid-rs` chain.

  Post-Phase-3-cutover, Elixir no longer runs any fetch/decode/score
  work for the propagation grid. The hourly cron fires this worker
  with empty args, and it inserts 19 `grid_tasks` rows (1 analysis
  f00 + 18 forecast f01..f18) for Rust to drain. Rust owns everything
  from there: HRRR fetch, wgrib2 decode, native-level duct merge,
  NEXRAD composite, commercial-link degradation, band scoring, and
  both the ProfilesFile (MessagePack) and the per-band score files.

  The old chain-step perform/2 clauses and the merge/score helpers
  moved to `rust/prop_grid_rs/src/pipeline.rs`. `Propagation.record_run_timing`
  is still called from this module when the Rust worker reports a
  chain step, through the PropagationNotifyListener path.
  """

  use Oban.Worker,
    queue: :propagation,
    priority: 0,
    max_attempts: 5,
    # Deduplicate seed jobs in a 1-hour window. The hourly cron fires
    # `%{}` args; unique protects against FreshnessMonitor re-fires
    # during an outage stacking multiple chains for the same run.
    unique: [period: 3600, states: [:available, :scheduled, :executing, :retryable]]

  alias Microwaveprop.Propagation.GridTaskEnqueuer
  alias Microwaveprop.Weather.HrrrClient

  require Logger

  @impl Oban.Worker
  def perform(%Oban.Job{args: args}) when args == %{} do
    seed_chain()
  end

  defp seed_chain do
    # HRRR takes ~45min to publish after the hour. Use 2 hours ago to
    # ensure availability.
    two_hours_ago = DateTime.add(DateTime.utc_now(), -2, :hour)
    run_time = two_hours_ago |> HrrrClient.nearest_hrrr_hour() |> DateTime.truncate(:second)

    Logger.info("PropagationGrid: seeding chain run_time=#{run_time} (f00 analysis + f01-f18 forecasts via grid_tasks)")

    case GridTaskEnqueuer.seed_with_analysis(run_time) do
      {:ok, _count} -> :ok
      {:error, reason} -> {:error, reason}
    end
  end
end
