syntax = "proto3";

package integration.openapi.v1beta1;

import "google/api/annotations.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
import "protoc-gen-openapiv2/options/annotations.proto";

option go_package = "github.com/tidbcloud/metrics-integration/global/integration/openapi/v1beta1";
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
  swagger: "2.0"
  host: "dedicated.tidbapi.com"
  info: {
    version: "v1beta1"
    title: "TiDB Cloud Integration API"
    description: "APIs to create, list and delete external metrics integrations (Datadog, New Relic, Prometheus) for TiDB Cloud clusters."
  }
  schemes: HTTPS
  consumes: "application/json"
  produces: "application/json"

  // Define the common error responses.
  responses: {
    key: "400"
    value: {
      description: "A request field is invalid."
      schema: {
        json_schema: {
          ref: ".google.rpc.Status"
          example: "{\"code\":400,\"message\":\"Invalid request: missing or invalid field\",\"details\": []}"
        }
      }
    }
  }
  responses: {
    key: "401"
    value: {
      description: "The API key cannot be authenticated."
      schema: {
        json_schema: {
          ref: ".google.rpc.Status"
          example: "{\"code\":401,\"message\":\"The API key cannot be authenticated.\",\"details\": []}"
        }
      }
    }
  }
  responses: {
    key: "403"
    value: {
      description: "The API key does not have permission to access the resource."
      schema: {
        json_schema: {
          ref: ".google.rpc.Status"
          example: "{\"code\":403,\"message\":\"The API key does not have permission to access the resource.\",\"details\": []}"
        }
      }
    }
  }
  responses: {
    key: "429"
    value: {
      description: "You have exceeded the rate limit."
      schema: {
        json_schema: {
          ref: ".google.rpc.Status"
          example: "{\"code\":429,\"message\":\"You have exceeded the rate limit.\",\"details\": []}"
        }
      }
    }
  }
  responses: {
    key: "500"
    value: {
      description: "Internal server error."
      schema: {
        json_schema: {
          ref: ".google.rpc.Status"
          example: "{\"code\":500,\"message\":\"Internal server error\",\"details\": []}"
        }
      }
    }
  }
};

enum DatadogSite {
  DATADOG_SITE_UNSPECIFIED = 0;
  US1 = 1;
  US3 = 2;
  US5 = 3;
  EU1 = 4;
  US1_FED = 5;
  AP1 = 6;
  AP2 = 7;
}

enum NewrelicSite {
  NEWRELIC_SITE_UNSPECIFIED = 0;
  US_OTLP = 1;
  EU_OTLP = 2;
}

enum IntegrationState {
  INTEGRATION_STATE_UNSPECIFIED = 0;
  NONE = 1;
  ACTIVE = 2;
  ERROR = 3;
}

enum IntegrationType {
  INTEGRATION_TYPE_UNSPECIFIED = 0;
  DATADOG = 1;
  NEWRELIC = 2;
  PROMETHEUS = 3;
}

message CreateIntegrationRequest {
  uint64 cluster_id = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "ClusterID"
    description: "The numeric TiDB Cloud cluster identifier. Specifies which cluster the integration applies to."
  }];

  IntegrationType type = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "IntegrationType"
    description: "The type of integration to create. Must match one of the supported IntegrationType enum values (DATADOG, NEWRELIC, PROMETHEUS)."
  }];

  // OpenAPI example for create request. Shows a valid DATADOG payload. Redocly
  // and other OpenAPI viewers will use this example when rendering request samples.
  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
    json_schema: {example: "{\"type\":\"DATADOG\",\"datadog\":{\"apiKey\":\"<DATADOG_API_KEY>\",\"site\":\"US1\"}}"}
  };

  oneof spec {
    CreateDatadogIntegrationRequest datadog = 3 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      title: "Datadog"
      description: "Configuration for the Datadog integration."
    }];
    CreateNewrelicIntegrationRequest newrelic = 4 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      title: "NewRelic"
      description: "Configuration for the New Relic integration."
    }];
    CreatePrometheusMetricsKeyRequest prometheus = 5 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      title: "Prometheus"
      description: "Configuration for the Prometheus integration."
    }];
  }
}

message IntegrationStatusResp {
  uint64 id = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "IntegrationID"
    description: "Unique identifier for the integration resource."
  }];

  IntegrationType type = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "IntegrationType"
    description: "The type of integration."
  }];

  oneof spec {
    DatadogIntegrationStatusResp datadog = 3 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      title: "Datadog"
      description: "Configuration for the Datadog integration."
    }];
    NewrelicIntegrationStatusResp newrelic = 4 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      title: "NewRelic"
      description: "Configuration for the New Relic integration."
    }];
    CreateMetricsKeyResp prometheus = 5 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      title: "Prometheus"
      description: "Configuration for the Prometheus integration."
    }];
  }

  google.protobuf.Timestamp create_time = 6 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "CreateTime"
    description: "Timestamp when the integration was created."
  }];
  google.protobuf.Timestamp update_time = 7 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "UpdateTime"
    description: "Timestamp when the integration was last updated."
  }];

  string creator = 8 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "Creator"
    description: "Identifier (username or system) of the actor who created the integration."
  }];

  // Example response for an active Datadog integration
  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
    json_schema: {example: "{\"id\":103,\"type\":\"DATADOG\",\"datadog\":{\"state\":\"ACTIVE\",\"statusReason\":\"\",\"site\":\"US1\",\"siteUrl\":\"https://app.datadoghq.com\",\"dashboardUrl\":\"https://app.datadoghq.com/dashboard/example\",\"maskedApiKey\":\"****3086\"},\"createTime\":\"2025-10-23T12:34:56Z\",\"updateTime\":\"2025-10-24T08:21:00Z\",\"creator\":\"admin@example.com\"}"}
  };
}

message ListIntegrationsRequest {
  uint64 cluster_id = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "ClusterID"
    description: "Cluster identifier used to filter integrations."
  }];
}

message DeleteIntegrationRequest {
  uint64 cluster_id = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "ClusterID"
    description: "Cluster identifier related to the integration to be deleted."
  }];

  uint64 id = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "IntegrationID"
    description: "Identifier of the integration to delete."
  }];
}

message CreateDatadogIntegrationRequest {
  string api_key = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "APIKey"
    description: "Datadog API key (write-only). The server will mask or not return the full key in list/status responses for security."
  }];

  DatadogSite site = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "DatadogSite"
    description: "Datadog regional site where metrics will be sent (e.g., US1, EU1)."
  }];

  // Example for the Datadog-specific payload
  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
    json_schema: {example: "{ \"apiKey\": \"<DATADOG_API_KEY>\", \"site\": \"US1\" }"}
  };
}

message CreateNewrelicIntegrationRequest {
  string api_key = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "APIKey"
    description: "New Relic ingestion key (write-only). The server will mask this value in responses."
  }];

  NewrelicSite site = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "NewRelicSite"
    description: "New Relic ingestion site selection (e.g., US_OTLP, EU_OTLP)."
  }];

  // Example for the New Relic-specific payload
  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
    json_schema: {example: "{ \"apiKey\": \"<NEWRELIC_API_KEY>\", \"site\": \"US_OTLP\" }"}
  };
}

message DatadogIntegrationStatusResp {
  IntegrationState state = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "State"
    description: "The current lifecycle state of the Datadog integration (NONE, ACTIVE, ERROR)."
  }];

  string status_reason = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "StatusReason"
    description: "When state is ERROR, provides a human-readable explanation of the failure."
  }];

  DatadogSite site = 3 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "DatadogSite"
    description: "Configured Datadog site for this integration."
  }];

  string site_url = 4 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "SiteURL"
    description: "The URL of the Datadog site configured for this integration."
  }];

  string dashboard_url = 5 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "DashboardURL"
    description: "A URL to a recommended dashboard in Datadog for viewing cluster metrics."
  }];

  string masked_api_key = 6 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "MaskedApiKey"
    description: "Masked representation of the Datadog API key (for display only)."
  }];

  // Example Datadog status response
  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
    json_schema: {example: "{ \"state\": \"ACTIVE\", \"statusReason\": \"\", \"site\": \"US1\", \"siteUrl\": \"https://app.datadoghq.com\", \"dashboardUrl\": \"https://app.datadoghq.com/dashboard/example\", \"maskedApiKey\": \"****3086\" }"}
  };
}

message NewrelicIntegrationStatusResp {
  IntegrationState state = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "State"
    description: "Current lifecycle state of the New Relic integration."
  }];
  string status_reason = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "StatusReason"
    description: "Human-readable reason when the integration is in ERROR state."
  }];
  NewrelicSite site = 3 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "NewRelicSite"
    description: "Configured New Relic ingestion site for this integration."
  }];
  string site_url = 4 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "SiteURL"
    description: "The New Relic site URL associated with this integration."
  }];
  string dashboard_url = 5 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "DashboardURL"
    description: "Link to a recommended New Relic dashboard for the cluster."
  }];
  string masked_api_key = 6 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "MaskedApiKey"
    description: "Masked New Relic key returned for display; not the full secret."
  }];

  // Example New Relic status response
  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
    json_schema: {example: "{ \"state\": \"ACTIVE\", \"statusReason\": \"\", \"site\": \"US_OTLP\", \"siteUrl\": \"https://one.newrelic.com\", \"dashboardUrl\": \"https://one.newrelic.com/dashboard/example\", \"maskedApiKey\": \"****abcd\" }"}
  };
}

message CreatePrometheusMetricsKeyRequest {
  // Example for Prometheus key creation (no body required; empty object shown)
  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
    json_schema: {example: "{ }"}
  };
}

message CreateMetricsKeyResp {
  string key = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "Key"
    description: "Generated Prometheus read key (sensitive). Provided when creating a new key."
  }];

  string query_endpoint = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "QueryEndpoint"
    description: "Prometheus-compatible HTTP endpoint to query metrics using the provided key."
  }];

  // Example response when creating a Prometheus metrics key
  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
    json_schema: {example: "{ \"key\": \"<PROMETHEUS_READ_KEY>\", \"queryEndpoint\": \"https://prom.example.com/api/v1/query\" }"}
  };
}

message ListPrometheusMetricsKeysRequest {
  uint64 cluster_id = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "ClusterID"
    description: "Cluster identifier to list Prometheus metrics keys for."
  }];
}

message ListIntegrationsResp {
  repeated IntegrationStatusResp items = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "Items"
    description: "Array of integration status objects associated with the cluster."
  }];

  int32 total = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
    title: "Total"
    description: "Total number of integrations for the cluster."
  }];

  // Example list response with one Datadog integration
  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
    json_schema: {example: "{ \"items\": [ { \"id\": 103, \"type\": \"DATADOG\", \"datadog\": { \"state\": \"ACTIVE\", \"site\": \"US1\", \"maskedApiKey\": \"****3086\" }, \"createTime\": \"2025-10-23T12:34:56Z\", \"updateTime\": \"2025-10-24T08:21:00Z\", \"creator\": \"admin@example.com\" } ], \"total\": 1 }"}
  };
}

service IntegrationService {
  rpc CreateIntegration(CreateIntegrationRequest) returns (IntegrationStatusResp) {
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "Create an integration"
      description: "Create a new external metrics integration (Datadog, New Relic or Prometheus) for the specified cluster."
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "bash"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value: "curl -X POST \"https://dedicated.tidbapi.com/v1beta1/clusters/123/integrations\" \\\n  --digest --user 'YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY' \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"type\": \"DATADOG\",\n    \"datadog\": {\n      \"apiKey\": \"<DATADOG_API_KEY>\",\n      \"site\": \"US1\"\n    }\n  }'"}
                }
              }
            }
          }
        }
      }
    };
    option (google.api.http) = {
      post: "/v1beta1/clusters/{cluster_id}/integrations"
      body: "*"
    };
  }

  rpc ListIntegrations(ListIntegrationsRequest) returns (ListIntegrationsResp) {
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "List integrations"
      description: "Return all integrations configured for a cluster, along with their runtime status."
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "bash"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value: "curl -X GET \"https://dedicated.tidbapi.com/v1beta1/clusters/123/integrations\" \\\n  --digest --user 'YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY' \\\n  -H \"Accept: application/json\""}
                }
              }
            }
          }
        }
      }
    };
    option (google.api.http) = {get: "/v1beta1/clusters/{cluster_id}/integrations"};
  }

  rpc DeleteIntegration(DeleteIntegrationRequest) returns (google.protobuf.Empty) {
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "Delete an integration"
      description: "Remove an integration identified by id from the given cluster."
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "bash"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value: "curl -X DELETE \"https://dedicated.tidbapi.com/v1beta1/clusters/123/integrations/456\" \\\n  --digest --user 'YOUR_PUBLIC_KEY:YOUR_PRIVATE_KEY' \\\n  -H \"Accept: application/json\""}
                }
              }
            }
          }
        }
      }
    };
    option (google.api.http) = {delete: "/v1beta1/clusters/{cluster_id}/integrations/{id}"};
  }
}
