defmodule Microwaveprop.Repo.Migrations.CreateHrrrFetchTasks do
  use Ecto.Migration

  # Hand-off queue between the Elixir enrichment enqueuer and the Rust
  # hrrr-point-worker (Phase 3 Stream C). One row per valid_time with a
  # JSONB array of {lat, lon} points the workers needs to extract from
  # that hour's HRRR cycle. Rust claims by SKIP LOCKED, fetches the
  # GRIB2 once, extracts every point in the batch, bulk-upserts to
  # hrrr_profiles, and marks the row done.
  def change do
    create table(:hrrr_fetch_tasks, primary_key: false) do
      add :id, :binary_id, primary_key: true
      add :valid_time, :utc_datetime, null: false

      # [{"lat": f, "lon": f}, …] — additional points for the same
      # valid_time get merged via jsonb array-union UPSERT so a
      # backfill tick doesn't schedule a new row per contact.
      add :points, :map, null: false, default: fragment("'[]'::jsonb")

      add :status, :string, null: false, default: "queued"
      add :attempt, :integer, null: false, default: 0
      add :claimed_at, :utc_datetime_usec
      add :completed_at, :utc_datetime_usec
      add :error, :text

      timestamps(type: :utc_datetime)
    end

    # One task per valid_time. Merges all points for the hour into a
    # single fetch so a full backfill scan costs one GRIB2 download
    # per hour, not one per contact.
    create unique_index(:hrrr_fetch_tasks, [:valid_time])

    # Hot-path claim query scans the queued subset.
    create index(:hrrr_fetch_tasks, [:status],
             where: "status = 'queued'",
             name: :hrrr_fetch_tasks_queued_idx
           )

    # Prune index for retention.
    create index(:hrrr_fetch_tasks, [:completed_at])
  end
end
