defmodule Microwaveprop.Radio.ImportRun do
  @moduledoc """
  Tracks an async CSV import: the full set of rows to process, running
  counters the `ContactImportWorker` increments as it processes chunks,
  and a status that moves from `"pending"` → `"running"` → `"complete"`
  (or `"failed"`).

  The `rows` field is a JSONB blob shaped as `%{"rows" => [...], "refinement_ids" => [...]}`
  so workers can tell which rows are new-contact inserts vs refinements
  of an existing contact.
  """
  use Ecto.Schema

  import Ecto.Changeset

  @primary_key {:id, :binary_id, autogenerate: true}
  @foreign_key_type :binary_id

  @statuses ~w(pending running complete failed)

  schema "import_runs" do
    field :submitter_email, :string
    field :rows, :map
    field :total_rows, :integer
    field :processed_rows, :integer, default: 0
    field :imported_count, :integer, default: 0
    field :refined_count, :integer, default: 0
    field :error_count, :integer, default: 0
    field :errors, :map, default: %{}
    field :status, :string, default: "pending"
    field :started_at, :utc_datetime_usec
    field :completed_at, :utc_datetime_usec

    timestamps(type: :utc_datetime_usec)
  end

  @type t :: %__MODULE__{}

  @cast_fields ~w(submitter_email rows total_rows processed_rows imported_count
                  refined_count error_count errors status started_at completed_at)a
  @required_fields ~w(submitter_email rows total_rows)a

  @spec statuses() :: [String.t()]
  def statuses, do: @statuses

  @spec changeset(t() | Ecto.Changeset.t(), map()) :: Ecto.Changeset.t()
  def changeset(run, attrs) do
    run
    |> cast(attrs, @cast_fields)
    |> validate_required(@required_fields)
    |> validate_inclusion(:status, @statuses)
    |> validate_number(:total_rows, greater_than_or_equal_to: 0)
    |> validate_number(:processed_rows, greater_than_or_equal_to: 0)
    |> validate_number(:imported_count, greater_than_or_equal_to: 0)
    |> validate_number(:refined_count, greater_than_or_equal_to: 0)
    |> validate_number(:error_count, greater_than_or_equal_to: 0)
  end
end
