defmodule BDS.Publishing.PublishJob do
  @moduledoc false

  use Ecto.Schema
  import Ecto.Changeset

  @primary_key {:id, :string, autogenerate: false}
  @foreign_key_type :string

  @type ssh_mode :: :scp | :rsync
  @type status :: :pending | :running | :completed | :failed

  @type t :: %__MODULE__{
          id: String.t() | nil,
          project_id: String.t() | nil,
          ssh_host: String.t() | nil,
          ssh_user: String.t() | nil,
          ssh_remote_path: String.t() | nil,
          ssh_mode: ssh_mode(),
          status: status(),
          task_id: String.t() | nil,
          targets: [String.t()],
          error: String.t() | nil,
          inserted_at: integer() | nil,
          updated_at: integer() | nil
        }

  schema "publish_jobs" do
    field :project_id, :string
    field :ssh_host, :string
    field :ssh_user, :string
    field :ssh_remote_path, :string
    field :ssh_mode, Ecto.Enum, values: [:scp, :rsync], default: :scp
    field :status, Ecto.Enum, values: [:pending, :running, :completed, :failed], default: :pending
    field :task_id, :string
    field :targets, {:array, :string}, default: []
    field :error, :string
    field :inserted_at, :integer
    field :updated_at, :integer
  end

  @spec changeset(t() | Ecto.Changeset.t(), map()) :: Ecto.Changeset.t()
  def changeset(job, attrs) do
    job
    |> cast(
      attrs,
      [
        :id,
        :project_id,
        :ssh_host,
        :ssh_user,
        :ssh_remote_path,
        :ssh_mode,
        :status,
        :task_id,
        :targets,
        :error,
        :inserted_at,
        :updated_at
      ],
      empty_values: [nil]
    )
    |> validate_required([
      :id,
      :project_id,
      :ssh_host,
      :ssh_user,
      :ssh_remote_path,
      :ssh_mode,
      :status,
      :targets,
      :inserted_at,
      :updated_at
    ])
    |> foreign_key_constraint(:project_id)
  end
end
