defmodule Ash.Resource.Actions.Action do
  @moduledoc "Represents a custom action on a resource."

  defstruct [
    constraints: [],
    touches_resources: [],
    arguments: [],
    transaction?: false,
    primary?: false,
    type: :action

  @type t :: %__MODULE__{
          type: :action,
          name: atom,
          description: String.t() | nil,
          arguments: [Ash.Resource.Actions.Argument.t()],
          touches_resources: [Ash.Resource.t()],
          constraints: Keyword.t(),
          run: {module, Keyword.t()},
          returns: Ash.Type.t(),
          primary?: boolean,
          transaction?: boolean

  import Ash.Resource.Actions.SharedOptions

  @global_opts shared_options()
  @opt_schema [
                returns: [
                  type: Ash.OptionsHelpers.ash_type(),
                  doc: "The return type of the action. See `Ash.Type` for more."
                constraints: [
                  type: :keyword_list,
                  doc: """
                  Constraints for the return type.
                  For more information see the specific type's documentation,
                  for general type information see `Ash.Type` and
                  for practical example [see the constraints topic](/documentation/topics/
                run: [
                    {:spark_function_behaviour, Ash.Resource.Actions.Implementation,
                     {Ash.Resource.Action.ImplementationFunction, 2}}
              |> Spark.OptionsHelpers.merge_schemas(
                "Action Options"

  @doc false
  def opt_schema, do: @opt_schema