// This proto file was generated from data-deletion-api.yml.
// Care should be taken while both files exist to maintain backwards compatibility with the Conjure generated code.

syntax = "proto3";

package nominal.storage.v1;

import "buf/validate/validate.proto";
import "google/api/annotations.proto";
import "nominal/protos/gen/v1/alias.proto";
import "nominal/protos/types/time/time.proto";

option java_multiple_files = true;
option java_package = "io.nominal.storage.v1";

message DeleteDataRequest {
  string data_source_rid = 1 [(nominal.gen.v1.alias) = {java_name: "io.nominal.api.rids.NominalDataSourceOrDatasetRid"}];

  // If specified, will only delete data within the given time range.
  // If not specified, will delete data across all time.
  optional nominal.types.time.Range time_range = 2;

  // If specified, will only delete data that fully matches the given tags.
  // If not specified, will delete data across all tags.
  map<string, string> tags = 3 [(nominal.gen.v1.alias) = {
    key_java_name: "io.nominal.api.TagName"
    value_java_name: "io.nominal.api.TagValue"
  }];

  // If specified, will only delete data that has an exact channel name match with the given names.
  // If not specified, will delete data across all channels.
  repeated string channel_names = 4 [(nominal.gen.v1.alias) = {java_name: "io.nominal.api.Channel"}];

  // If true and tags, channelNames, and timeRange are empty, will also delete associated channel metadata.
  // Otherwise, will only delete raw data. This is to guarantee that you are not orphaning data unintentionally
  // by deleting the metadata.
  bool delete_metadata = 5;
}

message DeleteDataResponse {}

// Identifies a channel with its associated tags.
message ChannelWithTags {
  string channel = 1 [(nominal.gen.v1.alias) = {java_name: "io.nominal.api.Channel"}];

  map<string, string> tags = 2 [(nominal.gen.v1.alias) = {
    key_java_name: "io.nominal.api.TagName"
    value_java_name: "io.nominal.api.TagValue"
  }];
}

message DeleteChannelWithTagsRequest {
  string data_source_rid = 1 [
    (buf.validate.field).required = true,
    (nominal.gen.v1.alias) = {java_name: "io.nominal.api.rids.NominalDataSourceOrDatasetRid"}
  ];

  // If channel is provided, only channels with tags matching that channel will be deleted.
  optional string channel = 2 [(nominal.gen.v1.alias) = {java_name: "io.nominal.api.Channel"}];

  // At least one tag must be specified in the request. Deletes all data containing the specified tags.
  map<string, string> tags = 3 [
    (nominal.gen.v1.alias) = {
      key_java_name: "io.nominal.api.TagName"
      value_java_name: "io.nominal.api.TagValue"
    },
    (buf.validate.field).map.min_pairs = 1
  ];

  // When false, the request does not apply the deletions and instead returns the list of channels with tags
  // that would be deleted. When true, the deletions are applied.
  bool apply = 4;

  // !!! WARNING !!!
  // When true, skips the soft-delete queue and permanently makes the channel and tags combinations unviewable.
  // This effect is IMMEDIATE and CANNOT be undone.
  // Requires apply to be true to have any effect.
  bool skip_hard_delete = 5;
}

message DeleteChannelWithTagsResponse {
  // The list of ChannelWithTags that were deleted or would be deleted (when apply is false).
  repeated ChannelWithTags channel_with_tags = 1;
}

message UndeleteChannelWithTagsRequest {
  string data_source_rid = 1 [
    (buf.validate.field).required = true,
    (nominal.gen.v1.alias) = {java_name: "io.nominal.api.rids.NominalDataSourceOrDatasetRid"}
  ];

  repeated ChannelWithTags channel_with_tags = 2 [(buf.validate.field).repeated = {
    min_items: 1
    max_items: 1000
  }];
}

message UndeleteChannelWithTagsResponse {}

// Data Deletion Service manages deletion of stored data.
service DataDeletionService {
  // Deletes stored data. This is an irreversible operation so be careful about specified
  // time range, channel names, and tag scope. requires the user to be an admin for the organization.
  rpc DeleteData(DeleteDataRequest) returns (DeleteDataResponse) {
    option (google.api.http) = {
      post: "/storage/data-deletion/v1/delete-data"
      body: "*"
    };
  }

  // Deletes channels with tags within a data source.
  // Requires DATASOURCE__DELETE_DATA permission on the data source.
  // Deletions are soft — deleted channels with tags are marked for deletion and will eventually be hard deleted.
  // The request will be rejected if there are too many pending deletions for the data source.
  // Throws if the request matches too many channels with tags.
  rpc DeleteChannelWithTags(DeleteChannelWithTagsRequest) returns (DeleteChannelWithTagsResponse) {
    option (google.api.http) = {
      post: "/storage/data-deletion/v1/delete-channel-with-tags"
      body: "*"
    };
  }

  // Best effort to undelete channels with tags within a data source.
  // Requires DATASOURCE__DELETE_DATA permission on the data source.
  // The batch size of channels with tags in the request must be <= 1000.
  rpc UndeleteChannelWithTags(UndeleteChannelWithTagsRequest) returns (UndeleteChannelWithTagsResponse) {
    option (google.api.http) = {
      post: "/storage/data-deletion/v1/undelete-channel-with-tags"
      body: "*"
    };
  }
}
