// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package google.cloud.storagebatchoperations.v1;

import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/protobuf/timestamp.proto";
import "google/rpc/code.proto";

option csharp_namespace = "Google.Cloud.StorageBatchOperations.V1";
option go_package = "cloud.google.com/go/storagebatchoperations/apiv1/storagebatchoperationspb;storagebatchoperationspb";
option java_multiple_files = true;
option java_outer_classname = "StorageBatchOperationsTypesProto";
option java_package = "com.google.cloud.storagebatchoperations.v1";
option php_namespace = "Google\\Cloud\\StorageBatchOperations\\V1";
option ruby_package = "Google::Cloud::StorageBatchOperations::V1";
option (google.api.resource_definition) = {
  type: "cloudkms.googleapis.com/CryptoKey"
  pattern: "projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}"
};

// The Storage Batch Operations Job description.
message Job {
  option (google.api.resource) = {
    type: "storagebatchoperations.googleapis.com/Job"
    pattern: "projects/{project}/locations/{location}/jobs/{job}"
    plural: "jobs"
    singular: "job"
  };

  // Describes state of a job.
  enum State {
    // Default value. This value is unused.
    STATE_UNSPECIFIED = 0;

    // In progress.
    RUNNING = 1;

    // Completed successfully.
    SUCCEEDED = 2;

    // Cancelled by the user.
    CANCELED = 3;

    // Terminated due to an unrecoverable failure.
    FAILED = 4;
  }

  // Identifier. The resource name of the Job. job_id is unique
  // within the project, that is either set by the customer or
  // defined by the service. Format:
  // projects/{project}/locations/global/jobs/{job_id} .
  // For example: "projects/123456/locations/global/jobs/job01".
  string name = 1 [(google.api.field_behavior) = IDENTIFIER];

  // Optional. A description provided by the user for the job. Its max length is
  // 1024 bytes when Unicode-encoded.
  string description = 2 [(google.api.field_behavior) = OPTIONAL];

  // Specifies objects to be transformed.
  oneof source {
    // Specifies a list of buckets and their objects to be transformed.
    BucketList bucket_list = 19;
  }

  // Operation to be performed on the objects.
  oneof transformation {
    // Changes object hold status.
    PutObjectHold put_object_hold = 5;

    // Delete objects.
    DeleteObject delete_object = 6;

    // Updates object metadata. Allows updating fixed-key and custom metadata
    // and fixed-key metadata i.e. Cache-Control, Content-Disposition,
    // Content-Encoding, Content-Language, Content-Type, Custom-Time.
    PutMetadata put_metadata = 8;

    // Rewrite the object and updates metadata like KMS key.
    RewriteObject rewrite_object = 20;
  }

  // Optional. Logging configuration.
  LoggingConfig logging_config = 9 [(google.api.field_behavior) = OPTIONAL];

  // Output only. The time that the job was created.
  google.protobuf.Timestamp create_time = 10
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The time that the job was scheduled.
  google.protobuf.Timestamp schedule_time = 11
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The time that the job was completed.
  google.protobuf.Timestamp complete_time = 12
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Information about the progress of the job.
  Counters counters = 13 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Summarizes errors encountered with sample error log entries.
  repeated ErrorSummary error_summaries = 14
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. State of the job.
  State state = 15 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Describes list of buckets and their objects to be transformed.
message BucketList {
  // Describes configuration of a single bucket and its objects to be
  // transformed.
  message Bucket {
    // Required. Bucket name for the objects to be transformed.
    string bucket = 1 [(google.api.field_behavior) = REQUIRED];

    // Specifies objects to be transformed.
    oneof object_configuration {
      // Specifies objects matching a prefix set.
      PrefixList prefix_list = 2;

      // Specifies objects in a manifest file.
      Manifest manifest = 3;
    }
  }

  // Required. List of buckets and their objects to be transformed. Currently,
  // only one bucket configuration is supported. If multiple buckets are
  // specified, an error will be returned.
  repeated Bucket buckets = 1 [(google.api.field_behavior) = REQUIRED];
}

// Describes list of objects to be transformed.
message Manifest {
  // Required. `manifest_location` must contain the manifest source file that is
  // a CSV file in a Google Cloud Storage bucket. Each row in the file must
  // include the object details i.e. BucketId and Name. Generation may
  // optionally be specified. When it is not specified the live object is acted
  // upon.
  //  `manifest_location` should either be
  // 1) An absolute path to the object in the format of
  // `gs://bucket_name/path/file_name.csv`.
  // 2) An absolute path with a single wildcard character in the file name, for
  // example `gs://bucket_name/path/file_name*.csv`.
  // If manifest location is specified with a wildcard, objects in all manifest
  // files matching the pattern will be acted upon.
  string manifest_location = 2 [(google.api.field_behavior) = REQUIRED];
}

// Describes prefixes of objects to be transformed.
message PrefixList {
  // Optional. Include prefixes of the objects to be transformed.
  // * Supports full object name
  // * Supports prefix of the object name
  // * Wildcards are not supported
  // * Supports empty string for all objects in a bucket.
  repeated string included_object_prefixes = 2
      [(google.api.field_behavior) = OPTIONAL];
}

// Describes options to update object hold.
message PutObjectHold {
  // Describes the status of the hold.
  enum HoldStatus {
    // Default value, Object hold status will not be changed.
    HOLD_STATUS_UNSPECIFIED = 0;

    // Places the hold.
    SET = 1;

    // Releases the hold.
    UNSET = 2;
  }

  // Required. Updates object temporary holds state. When object temporary hold
  // is set, object cannot be deleted or replaced.
  HoldStatus temporary_hold = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. Updates object event based holds state. When object event based
  // hold is set, object cannot be deleted or replaced. Resets object's time in
  // the bucket for the purposes of the retention period.
  HoldStatus event_based_hold = 2 [(google.api.field_behavior) = REQUIRED];
}

// Describes options to delete an object.
message DeleteObject {
  // Required. Controls deletion behavior when versioning is enabled for the
  // object's bucket. If true both live and noncurrent objects will be
  // permanently deleted. Otherwise live objects in versioned buckets will
  // become noncurrent and objects that were already noncurrent will be skipped.
  // This setting doesn't have any impact on the Soft Delete feature. All
  // objects deleted by this service can be be restored for the duration of the
  // Soft Delete retention duration if enabled. If enabled and the manifest
  // doesn't specify an object's generation, a GetObjectMetadata call (a Class B
  // operation) will be made to determine the live object generation.
  bool permanent_object_deletion_enabled = 1
      [(google.api.field_behavior) = REQUIRED];
}

// Describes options for object rewrite.
message RewriteObject {
  // Required. Resource name of the Cloud KMS key that will be used to encrypt
  // the object. The Cloud KMS key must be located in same location as the
  // object. Refer to
  // https://cloud.google.com/storage/docs/encryption/using-customer-managed-keys#add-object-key
  // for additional documentation. Format:
  // projects/{project}/locations/{location}/keyRings/{keyring}/cryptoKeys/{key}
  // For example:
  // "projects/123456/locations/us-central1/keyRings/my-keyring/cryptoKeys/my-key".
  // The object will be rewritten and set with the specified KMS key.
  optional string kms_key = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "cloudkms.googleapis.com/CryptoKey"
    }
  ];
}

// Describes options for object metadata update.
message PutMetadata {
  // Optional. Updates objects Content-Disposition fixed metadata. Unset values
  // will be ignored. Set empty values to clear the metadata. Refer
  // https://cloud.google.com/storage/docs/metadata#content-disposition for
  // additional documentation.
  optional string content_disposition = 1
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. Updates objects Content-Encoding fixed metadata. Unset values
  // will be ignored. Set empty values to clear the metadata. Refer to
  // documentation in
  // https://cloud.google.com/storage/docs/metadata#content-encoding.
  optional string content_encoding = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Updates objects Content-Language fixed metadata. Refer to ISO
  // 639-1 language codes for typical values of this metadata. Max length 100
  // characters. Unset values will be ignored. Set empty values to clear the
  // metadata. Refer to documentation in
  // https://cloud.google.com/storage/docs/metadata#content-language.
  optional string content_language = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Updates objects Content-Type fixed metadata. Unset values will be
  // ignored.
  //  Set empty values to clear the metadata. Refer to documentation in
  //  https://cloud.google.com/storage/docs/metadata#content-type
  optional string content_type = 4 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Updates objects Cache-Control fixed metadata. Unset values will
  // be
  //  ignored. Set empty values to clear the metadata.
  //  Additionally, the value for Custom-Time cannot decrease. Refer to
  //  documentation in
  // https://cloud.google.com/storage/docs/metadata#caching_data.
  optional string cache_control = 5 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Updates objects Custom-Time fixed metadata. Unset values will be
  // ignored. Set empty values to clear the metadata. Refer to documentation in
  // https://cloud.google.com/storage/docs/metadata#custom-time.
  optional string custom_time = 6 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Updates objects custom metadata. Adds or sets individual custom
  // metadata key value pairs on objects. Keys that are set with empty custom
  // metadata values will have its value cleared. Existing custom metadata not
  // specified with this flag is not changed. Refer to documentation in
  // https://cloud.google.com/storage/docs/metadata#custom-metadata
  map<string, string> custom_metadata = 7
      [(google.api.field_behavior) = OPTIONAL];
}

// A summary of errors by error code, plus a count and sample error log
// entries.
message ErrorSummary {
  // Required. The canonical error code.
  google.rpc.Code error_code = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. Number of errors encountered per `error_code`.
  int64 error_count = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. Sample error logs.
  repeated ErrorLogEntry error_log_entries = 3
      [(google.api.field_behavior) = REQUIRED];
}

// An entry describing an error that has occurred.
message ErrorLogEntry {
  // Required. Output only. Object URL. e.g. gs://my_bucket/object.txt
  string object_uri = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.field_behavior) = OUTPUT_ONLY
  ];

  // Optional. Output only. At most 5 error log entries are recorded for a given
  // error code for a job.
  repeated string error_details = 3 [
    (google.api.field_behavior) = OPTIONAL,
    (google.api.field_behavior) = OUTPUT_ONLY
  ];
}

// Describes details about the progress of the job.
message Counters {
  // Output only. Number of objects listed.
  int64 total_object_count = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Number of objects completed.
  int64 succeeded_object_count = 2 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Number of objects failed.
  int64 failed_object_count = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Specifies the Cloud Logging behavior.
message LoggingConfig {
  // Loggable actions types.
  enum LoggableAction {
    // Illegal value, to avoid allowing a default.
    LOGGABLE_ACTION_UNSPECIFIED = 0;

    // The corresponding transform action in this job.
    TRANSFORM = 6;
  }

  // Loggable action states filter.
  enum LoggableActionState {
    // Illegal value, to avoid allowing a default.
    LOGGABLE_ACTION_STATE_UNSPECIFIED = 0;

    // `LoggableAction` completed successfully. `SUCCEEDED` actions are
    // logged as [INFO][google.logging.type.LogSeverity.INFO].
    SUCCEEDED = 1;

    // `LoggableAction` terminated in an error state. `FAILED` actions
    // are logged as [ERROR][google.logging.type.LogSeverity.ERROR].
    FAILED = 2;
  }

  // Required. Specifies the actions to be logged.
  repeated LoggableAction log_actions = 1
      [(google.api.field_behavior) = REQUIRED];

  // Required. States in which Action are logged.If empty, no logs are
  // generated.
  repeated LoggableActionState log_action_states = 2
      [(google.api.field_behavior) = REQUIRED];
}
