// Copyright 2026 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.appoptimize.v1beta;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/longrunning/operations.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";

option csharp_namespace = "Google.Cloud.AppOptimize.V1Beta";
option go_package = "cloud.google.com/go/appoptimize/apiv1beta/appoptimizepb;appoptimizepb";
option java_multiple_files = true;
option java_outer_classname = "AppOptimizeProto";
option java_package = "com.google.cloud.appoptimize.v1beta";
option php_namespace = "Google\\Cloud\\AppOptimize\\V1beta";

// Resource definition for App Hub Application.
option (google.api.resource_definition) = {
  type: "apphub.googleapis.com/Application"
  pattern: "projects/{project}/locations/{location}/applications/{application}"
};

// Service for managing and querying optimization reports.
service AppOptimize {
  option (google.api.default_host) = "appoptimize.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/cloud-platform";

  // Creates a new report.
  //
  // This initiates a long-running operation that, upon completion, results
  // in a report resource. Once the report is created, its results can be read
  // via `ReadReport`.
  rpc CreateReport(CreateReportRequest) returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1beta/{parent=projects/*/locations/*}/reports"
      body: "report"
    };
    option (google.api.method_signature) = "parent,report,report_id";
    option (google.longrunning.operation_info) = {
      response_type: "Report"
      metadata_type: "OperationMetadata"
    };
  }

  // Retrieves the details of a report configuration.
  rpc GetReport(GetReportRequest) returns (Report) {
    option (google.api.http) = {
      get: "/v1beta/{name=projects/*/locations/*/reports/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Lists reports within a given project.
  rpc ListReports(ListReportsRequest) returns (ListReportsResponse) {
    option (google.api.http) = {
      get: "/v1beta/{parent=projects/*/locations/*}/reports"
    };
    option (google.api.method_signature) = "parent";
  }

  // Deletes the specified report.
  rpc DeleteReport(DeleteReportRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v1beta/{name=projects/*/locations/*/reports/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Reads data within a specified report.
  rpc ReadReport(ReadReportRequest) returns (ReadReportResponse) {
    option (google.api.http) = {
      post: "/v1beta/{name=projects/*/locations/*/reports/*}:read"
      body: "*"
    };
    option (google.api.method_signature) = "name";
  }
}

// Request message for the `CreateReport` method.
message CreateReportRequest {
  // Required. The parent Google Cloud project that will own the report.
  //
  // This value does not define the scope of the report data. See `Report.scope`
  // for setting the data scope.
  //
  // Format: `projects/{project}/locations/{location}`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "appoptimize.googleapis.com/Report"
    }
  ];

  // Required. The ID to use for this report. This ID must be unique within
  // the parent project and should comply with RFC 1034 restrictions (letters,
  // numbers, and hyphen, with the first character a letter, the last a letter
  // or a number, and a 63 character maximum).
  string report_id = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. The report resource to create.
  Report report = 3 [(google.api.field_behavior) = REQUIRED];
}

// A configuration that defines the parameters for the data represented by a
// report.
message Report {
  option (google.api.resource) = {
    type: "appoptimize.googleapis.com/Report"
    pattern: "projects/{project}/locations/{location}/reports/{report}"
    plural: "reports"
    singular: "report"
  };

  // Defines this report's expiration time.
  oneof expiration {
    // Output only. Timestamp in UTC of when this report expires. Once the
    // report expires, it will no longer be accessible and the report's
    // underlying data will be deleted.
    google.protobuf.Timestamp expire_time = 6
        [(google.api.field_behavior) = OUTPUT_ONLY];
  }

  // Identifier. The name of this report.
  string name = 1 [(google.api.field_behavior) = IDENTIFIER];

  // Required. A list of dimensions to include in the report. Supported values:
  //
  //   * `project`
  //   * `application`
  //   * `service_or_workload`
  //   * `resource`
  //   * `resource_type`
  //   * `location`
  //   * `product_display_name`
  //   * `sku`
  //   * `month`
  //   * `day`
  //   * `hour`
  //
  // To aggregate results by time, specify at least one time dimension
  // (`month`, `day`, or `hour`). All time dimensions use Pacific Time,
  // respect Daylight Saving Time (DST), and follow these ISO 8601 formats:
  //
  //   * `month`: `YYYY-MM` (e.g., `2024-01`)
  //   * `day`: `YYYY-MM-DD` (e.g., `2024-01-10`)
  //   * `hour`: `YYYY-MM-DDTHH` (e.g., `2024-01-10T00`)
  //
  // If the time range filter does not align with the selected time dimension,
  // the range is expanded to encompass the full period of the finest-grained
  // time dimension.
  //
  // For example, if the filter is `2026-01-10` through `2026-01-12` and the
  // `month` dimension is selected, the effective time range expands to include
  // all of January (`2026-01-01` to `2026-02-01`).
  repeated string dimensions = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. A list of metrics to include in the report. Supported values:
  //
  //   * `cost`
  //   * `cpu_mean_utilization`
  //   * `cpu_usage_core_seconds`
  //   * `cpu_allocation_core_seconds`
  //   * `cpu_p95_utilization`
  //   * `memory_mean_utilization`
  //   * `memory_usage_byte_seconds`
  //   * `memory_allocation_byte_seconds`
  //   * `memory_p95_utilization`
  repeated string metrics = 7 [(google.api.field_behavior) = REQUIRED];

  // Optional. The resource containers for which to fetch data. Default is the
  // project specified in the report's parent.
  repeated Scope scopes = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. A Common Expression Language (CEL) expression used to filter the
  // data for the report.
  //
  // Predicates may refer to any dimension. Filtering must conform to these
  // constraints:
  //
  //   * All string field predicates must use exact string matches.
  //   * Multiple predicates referring to the same string field must be joined
  //     using the logical OR operator ('||').
  //   * All other predicates must be joined using the logical AND operator
  //     (`&&`).
  //   * A predicate on a time dimension (e.g., `day`) specifying the start time
  //     must use a greater-than-or-equal-to comparison (`>=`).
  //   * A predicate on a time dimension specifying the end time must use a
  //     less-than comparison (`<`).
  //
  // Examples:
  //
  //   1. Filter by a specific resource type:
  //      `"resource_type == 'compute.googleapis.com/Instance'"`
  //
  //   2. Filter data points that fall within a specific absolute time interval:
  //      `"hour >= timestamp('2024-01-01T00:00:00Z') &&
  //      hour < timestamp('2024-02-01T00:00:00Z')"`
  //
  //   3. Filter data points that fall within the past 72 hours:
  //      `"hour >= now - duration('72h')"`
  //
  //   4. Combine string predicate with time interval predicate:
  //      `"(location == 'us-east1' || location == 'us-west1') &&
  //       hour >= timestamp('2023-12-01T00:00:00Z') &&
  //       hour < timestamp('2024-02-01T00:00:00Z')"`
  //
  // If the filter omits time dimensions (`month`, `day`, `hour`), the report
  // defaults to a 7-day range ending at the previous Pacific Time midnight,
  // with Daylight Saving Time (DST) applied.
  //
  // For example, if the current Pacific Time is `2026-01-05T12:00:00`,
  // the default range is `2025-12-29T00:00:00` to `2026-01-05T00:00:00` Pacific
  // time.
  string filter = 4 [(google.api.field_behavior) = OPTIONAL];
}

// Specifies the report scope.
message Scope {
  oneof scope {
    // Required. A Google Cloud Platform project to fetch data from.
    //
    // Format: `"projects/{project}"`.
    string project = 1 [
      (google.api.field_behavior) = REQUIRED,
      (google.api.resource_reference) = {
        type: "cloudresourcemanager.googleapis.com/Project"
      }
    ];

    // Required. An App Hub Application to fetch data from.
    //
    // Format:
    // `"projects/{project}/locations/{location}/applications/{application}"`.
    string application = 2 [
      (google.api.field_behavior) = REQUIRED,
      (google.api.resource_reference) = {
        type: "apphub.googleapis.com/Application"
      }
    ];
  }
}

// Request message for the `GetReport` method.
message GetReportRequest {
  // Required. The name of the report to retrieve.
  //
  // Format: `projects/{project}/locations/{location}/reports/{report_id}`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "appoptimize.googleapis.com/Report"
    }
  ];
}

// Request message for the `ListReports` method.
message ListReportsRequest {
  // Required. The parent project whose reports are to be listed.
  //
  // Format: `projects/{project}/locations/{location}`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "appoptimize.googleapis.com/Report"
    }
  ];

  // Optional. The maximum number of reports to return. The service may return
  // fewer than this value. If unspecified, the server will determine the number
  // of results to return.
  int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. A page token, received from a previous `ListReports` call.
  // Provide this to retrieve the subsequent page.
  //
  // When paginating, all other parameters provided to `ListReports` must match
  // the call that provided the page token.
  string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
}

// Response message for the `ListReports` method.
message ListReportsResponse {
  // The list of reports.
  repeated Report reports = 1;

  // A token that can be sent as `page_token` to retrieve the next page.
  // If this field is empty, there are no subsequent pages.
  string next_page_token = 2;
}

// Request message for the `DeleteReport` method.
message DeleteReportRequest {
  // Required. The name of the report to delete.
  //
  // Format: `projects/{project}/locations/{location}/reports/{report_id}`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "appoptimize.googleapis.com/Report"
    }
  ];

  // Optional. If set to true, and the report is not found, the request will
  // succeed but no action will be taken on the server.
  bool allow_missing = 2 [(google.api.field_behavior) = OPTIONAL];
}

// Request message for the `ReadReport` method.
message ReadReportRequest {
  // Required. The resource name of the report to query.
  //
  // Format: `projects/{project}/locations/{location}/reports/{report_id}`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "appoptimize.googleapis.com/Report"
    }
  ];

  // Optional. The maximum number of rows to return. The service may return
  // fewer than this value. If unspecified, at most 10,000 rows will be returned
  // per page. The maximum allowed value is 25,000; values above 25,000 are
  // coerced to 25,000.
  int32 page_size = 4 [(google.api.field_behavior) = OPTIONAL];

  // Optional. A page token, received from a previous `ReadReport` call, to
  // retrieve the subsequent page of results. When `page_token` is specified,
  // `job_reference` must also be provided from the previous response, and the
  // `statement` field must not be set.
  string page_token = 5 [(google.api.field_behavior) = OPTIONAL];
}

// Response message for the `ReadReport` method.
message ReadReportResponse {
  // A list of rows, where each row represents a record from the report.
  repeated google.protobuf.ListValue rows = 1;

  // The columns describing the structure of the data in the `rows` field.
  repeated Column columns = 5;

  // A token that can be sent as `page_token` in a subsequent `ReadReport`
  // request to retrieve the next page of results. If this field is empty,
  // there are no further pages.
  string next_page_token = 3;
}

// Describes a single column within `Columns`.
message Column {
  // The name of the column.
  //
  // This field:
  //
  //   * Contains only letters (a-z, A-Z), numbers (0-9), or underscores (_);
  //   * Start with a letter or underscore; and
  //   * Has a maximum length is 128 characters.
  string name = 1;

  // The data type of the column.
  //
  // Supported values include:
  //
  //   * `STRING`
  //   * `INT64`
  //   * `FLOAT64`
  //   * `BOOLEAN`
  //   * `TIMESTAMP`
  //   * `RECORD`
  //
  // `RECORD` indicates that the field contains a nested schema, described in
  // the `columns` property of this `Column`.
  string type = 2;

  // The mode of the column, indicating if it is nullable, required, or
  // repeated.
  //
  // Possible values:
  //
  //   * `NULLABLE`: The column allows NULL values.
  //   * `REQUIRED`: The column does not allow NULL values.
  //   * `REPEATED`: The column contains an array of values.
  string mode = 3;

  // If the `type` of this column is `RECORD`, this sub-field describes the
  // nested structure.
  repeated Column columns = 4;
}

// Represents metadata related to the creation of a Report. This value is
// embedded in the Operation object returned by `CreateReport`.
message OperationMetadata {}
