defmodule Microwaveprop.Workers.HrdpsGridWorkerTest do
  use Microwaveprop.DataCase, async: false
  use Oban.Testing, repo: Microwaveprop.Repo

  import Ecto.Query

  alias Microwaveprop.Repo
  alias Microwaveprop.Workers.HrdpsGridWorker

  setup do
    original = Application.get_env(:microwaveprop, :hrdps_cycle_available_fn)

    on_exit(fn ->
      if original,
        do: Application.put_env(:microwaveprop, :hrdps_cycle_available_fn, original),
        else: Application.delete_env(:microwaveprop, :hrdps_cycle_available_fn)
    end)
  end

  describe "pick_run_time/1" do
    test "returns the now-4h cycle when it's published" do
      Application.put_env(:microwaveprop, :hrdps_cycle_available_fn, fn _dt -> true end)

      now = ~U[2026-04-29 16:30:00Z]
      run_time = HrdpsGridWorker.pick_run_time(now)

      # now - 4h = 12:30Z; snap down to cycle = 12:00Z
      assert run_time == ~U[2026-04-29 12:00:00Z]
    end

    test "falls back to the previous cycle when fresh isn't yet published" do
      Application.put_env(:microwaveprop, :hrdps_cycle_available_fn, fn _dt -> false end)

      now = ~U[2026-04-29 16:30:00Z]
      run_time = HrdpsGridWorker.pick_run_time(now)

      # now - 10h = 06:30Z; snap down to cycle = 06:00Z
      assert run_time == ~U[2026-04-29 06:00:00Z]
    end
  end

  describe "perform/1" do
    test "seeds exactly one current-hour grid_task row tagged with source='hrdps'" do
      Application.put_env(:microwaveprop, :hrdps_cycle_available_fn, fn _dt -> true end)

      assert :ok = perform_job(HrdpsGridWorker, %{})

      rows =
        Repo.all(
          from(g in "grid_tasks",
            where: g.source == "hrdps",
            select: %{kind: g.kind, forecast_hour: g.forecast_hour}
          )
        )

      # One forecast row, no analysis. /weather only consumes current
      # hour so we don't pay the wgrib2 cost for the rest of the chain.
      assert length(rows) == 1
      [%{kind: kind, forecast_hour: fh}] = rows
      assert kind == "forecast"
      assert fh >= 1 and fh <= 18
    end

    test "is idempotent — re-running the worker for the same cycle inserts nothing extra" do
      Application.put_env(:microwaveprop, :hrdps_cycle_available_fn, fn _dt -> true end)

      assert :ok = perform_job(HrdpsGridWorker, %{})
      assert :ok = perform_job(HrdpsGridWorker, %{})

      total =
        Repo.one(from(g in "grid_tasks", where: g.source == "hrdps", select: count()))

      assert total == 1
    end
  end
end
