syntax = "proto3";

package bff.cluster_management.v1beta2;

import "bff/cluster_management/v1beta2/resources.proto";
import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "tidb_cloud_open_api/common/v1beta1/engine_type.proto";
import "tidb_cloud_open_api/common/v1beta1/region.proto";
import "tidb_cloud_open_api/common/v1beta1/service_plan.proto";
import "tidb_cloud_open_api/common/v1beta1/tag.proto";

option go_package = "bff/cluster_management/v1beta2";
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
  swagger: "2.0"
  host: ""
  base_path: "/v1beta2"
  info: {
    version: "v1beta2"
    title: "TiDB Cloud One Console API"
    description: "TiDB Cloud One Console API."
  }
  schemes: HTTPS
};

service TiDBService {
  rpc ListTidbs(ListTidbsRequest) returns (ListTidbsResponse) {
    option (google.api.http) = {get: "/tidbs"};
  }

  rpc GetTidb(GetTidbRequest) returns (Tidb) {
    option (google.api.http) = {get: "/tidbs/{tidb_id}"};
  }

  rpc GetClusterInventory(GetClusterInventoryRequest) returns (GetClusterInventoryResponse) {
    option (google.api.http) = {get: "/tidbs:inventory"};
  }

  rpc BindTags(BindTagsRequest) returns (BindTagsResponse) {
    option (google.api.http) = {
      post: "/tidbs/{tidb_id}:bindTags"
      body: "*"
    };
  }

  rpc UnbindTags(UnbindTagsRequest) returns (UnbindTagsResponse) {
    option (google.api.http) = {
      post: "/tidbs/{tidb_id}:unbindTags"
      body: "*"
    };
  }

  rpc MoveTiDB(MoveTiDBRequest) returns (MoveTiDBResponse) {
    option (google.api.http) = {
      post: "/tidbs/{tidb_id}:move"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {summary: "Move a tidb to another project"};
  }

  rpc BatchMoveTiDBs(BatchMoveTiDBsRequest) returns (BatchMoveTiDBsResponse) {
    option (google.api.http) = {
      post: "/tidbs:batchMove"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {summary: "Batch move tidbs to another project"};
  }

  rpc GetProjectMigrationTask(GetProjectMigrationTaskRequest) returns (ProjectMigrationTask) {
    option (google.api.http) = {get: "/project-migration"};
  }

  rpc ApproveProjectMigrationTask(ApproveProjectMigrationTaskRequest) returns (ApproveProjectMigrationTaskResponse) {
    option (google.api.http) = {
      post: "/project-migration:approve"
      body: "*"
    };
  }
}

service RegionService {
  rpc ListRegions(ListRegionsRequest) returns (ListRegionsResponse) {
    option (google.api.http) = {get: "/regions"};
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {summary: "List all regions"};
  }

  rpc ListCloudProviders(ListCloudProvidersRequest) returns (ListCloudProvidersResponse) {
    option (google.api.http) = {get: "/regions:listCloudProviders"};
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {summary: "List all cloud providers"};
  }
}

message ListTidbsRequest {
  repeated tidb_cloud_open_api.common.v1beta1.ServicePlan service_plans = 1 [(google.api.field_behavior) = OPTIONAL];
  repeated string tidb_ids = 3 [(google.api.field_behavior) = OPTIONAL];
  repeated tidb_cloud_open_api.common.v1beta1.Region.CloudProvider cloud_providers = 4 [(google.api.field_behavior) = OPTIONAL];
  repeated string region_ids = 5 [(google.api.field_behavior) = OPTIONAL];
  repeated string project_ids = 6 [(google.api.field_behavior) = OPTIONAL];

  string name = 7 [(google.api.field_behavior) = OPTIONAL];
  ViewMode view_mode = 8 [(google.api.field_behavior) = OPTIONAL];
  repeated string tags = 9 [(google.api.field_behavior) = OPTIONAL];

  // If specified, only TiDBs of the given engine types are returned.
  repeated tidb_cloud_open_api.common.v1beta1.EngineType engine_types = 11 [(google.api.field_behavior) = OPTIONAL];

  // When true, for Dedicated clusters only, skip Regional Server enrichment in
  // ListClusters (global-layer metadata only). Ignored when view_mode is MINI.
  // Ignored for Serverless and NextGen service plans.
  // Default false preserves the current FullView list item shape.
  optional bool global_meta_only = 10 [(google.api.field_behavior) = OPTIONAL];

  int32 page_size = 100 [(google.api.field_behavior) = OPTIONAL];

  string page_token = 101 [(google.api.field_behavior) = OPTIONAL];

  int32 skip = 102 [(google.api.field_behavior) = OPTIONAL];

  enum ViewMode {
    VIEW_MODE_UNSPECIFIED = 0;
    BASIC = 1;
    MINI = 2;
  }
}

message ListTidbsResponse {
  repeated Tidb tidbs = 1;

  int32 total_size = 100;

  string next_page_token = 101;
}

message GetTidbRequest {
  string tidb_id = 1 [(google.api.field_behavior) = REQUIRED];

  // When true, for Dedicated clusters only, skip Regional Server enrichment and
  // return global-layer metadata only (no endpoints, scaling progress, etc.).
  // Ignored for Serverless and NextGen service plans.
  // Default false preserves the current FullView response shape.
  optional bool global_meta_only = 2 [(google.api.field_behavior) = OPTIONAL];
}

message GetClusterInventoryRequest {}

message GetClusterInventoryResponse {
  repeated ClusterInventoryItem inventories = 1;
}

message ClusterInventoryItem {
  tidb_cloud_open_api.common.v1beta1.ServicePlan service_plan = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
  int32 limit = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  int32 current_count = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
}

message BindTagsRequest {
  string tidb_id = 1 [(google.api.field_behavior) = REQUIRED];
  repeated string tags = 2 [(google.api.field_behavior) = REQUIRED];
}

message BindTagsResponse {
  repeated tidb_cloud_open_api.common.v1beta1.Tag tags = 1;
}

message UnbindTagsRequest {
  string tidb_id = 1 [(google.api.field_behavior) = REQUIRED];
  repeated string tags = 2 [(google.api.field_behavior) = REQUIRED];
}

message UnbindTagsResponse {
  repeated tidb_cloud_open_api.common.v1beta1.Tag tags = 1;
}

message ListRegionsRequest {
  repeated tidb_cloud_open_api.common.v1beta1.Region.CloudProvider cloud_providers = 1 [(google.api.field_behavior) = OPTIONAL];
  repeated tidb_cloud_open_api.common.v1beta1.ServicePlan service_plans = 2 [(google.api.field_behavior) = OPTIONAL];
  ViewMode view_mode = 3 [(google.api.field_behavior) = OPTIONAL];

  enum ViewMode {
    VIEW_MODE_UNSPECIFIED = 0;
    SERVICE_PLAN_GROUP = 1;
    FLAT = 2;
  }
}

message ListRegionsResponse {
  oneof view {
    ServicePlanGroupedView service_plan_group_view = 1;
    FlatView flat_view = 2;
  }

  message ServicePlanGroupedView {
    repeated ServicePlanGroup items = 1;
  }

  message FlatView {
    repeated tidb_cloud_open_api.common.v1beta1.Region regions = 1;
  }

  message ServicePlanGroup {
    tidb_cloud_open_api.common.v1beta1.ServicePlan service_plan = 1;
    repeated tidb_cloud_open_api.common.v1beta1.Region regions = 2;
  }
}

message ListCloudProvidersRequest {
  repeated tidb_cloud_open_api.common.v1beta1.Region.CloudProvider cloud_providers = 1 [(google.api.field_behavior) = OPTIONAL];
  repeated tidb_cloud_open_api.common.v1beta1.ServicePlan service_plans = 2 [(google.api.field_behavior) = OPTIONAL];
}

message ListCloudProvidersResponse {
  repeated GroupedCloudProvider cloud_providers = 1;

  message GroupedCloudProvider {
    tidb_cloud_open_api.common.v1beta1.ServicePlan service_plan = 1;
    repeated tidb_cloud_open_api.common.v1beta1.Region.CloudProvider cloud_providers = 3;
  }
}

// MoveTiDBRequest moves a single Starter or Essential tidb to a target project.
message MoveTiDBRequest {
  // tidb_id is the ID of the TiDB to move.
  string tidb_id = 1 [(google.api.field_behavior) = REQUIRED];

  // target_project_id is the destination project.
  string target_project_id = 2 [(google.api.field_behavior) = REQUIRED];

  // new name of instance after move, if not provided, the name won't be changed.
  string name = 3 [(google.api.field_behavior) = OPTIONAL];
}

message MoveTiDBResponse {
  // tidb is the moved tidb.
  Tidb tidb = 1;
}

// BatchMoveTiDBsRequest moves multiple Starter/Essential TiDBs from one project to another.
// Max 1000 tidbs per request.
message BatchMoveTiDBsRequest {
  // source_project_id is the source project (required).
  string source_project_id = 1 [(google.api.field_behavior) = REQUIRED];

  // target_project_id is the destination project (required).
  string target_project_id = 2 [(google.api.field_behavior) = REQUIRED];

  // service_plans filters which service plans to move (optional; default: all supported plans).
  repeated tidb_cloud_open_api.common.v1beta1.ServicePlan service_plans = 3 [(google.api.field_behavior) = OPTIONAL];
}

message BatchMoveTiDBsResponse {
  // total is the number of TiDBs scheduled for migration.
  int32 total = 1;

  // failed_tidb_ids lists the IDs of TiDBs that failed to move.
  repeated string failed_tidb_ids = 2;

  // success_tidb_ids lists the IDs of TiDBs that were successfully moved.
  repeated string success_tidb_ids = 3;
}

message GetProjectMigrationTaskRequest {}

message ProjectMigrationTask {
  uint64 org_id = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
  State state = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  repeated Migration migrations = 3 [(google.api.field_behavior) = OUTPUT_ONLY];

  enum State {
    STATE_UNSPECIFIED = 0;
    PENDING = 1;
    RUNNING = 2;
    SUCCEED = 3;
    FAILED = 4;
  }
}

message Migration {
  uint64 source_project_id = 1 [(google.api.field_behavior) = REQUIRED];
  string source_project_name = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  uint64 target_project_id = 3 [(google.api.field_behavior) = OPTIONAL];
  string target_project_name = 4 [(google.api.field_behavior) = OPTIONAL];

  uint64 count_in_source_project = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
  uint64 count_in_target_project = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
}

message ApproveProjectMigrationTaskRequest {
  repeated Migration migrations = 3 [(google.api.field_behavior) = REQUIRED];
}

message ApproveProjectMigrationTaskResponse {
  ProjectMigrationTask task = 1;
}
