// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you 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 banyandb.cluster.v1;

import "banyandb/model/v1/write.proto";

option go_package = "github.com/apache/skywalking-banyandb/api/proto/banyandb/cluster/v1";

message VersionInfo {
  // file_format_version indicates the file format version used
  string file_format_version = 1;
  // compatible_file_format_version lists backward compatible versions
  repeated string compatible_file_format_version = 2;
  // api_version indicates the API semantic version
  string api_version = 3;
}

message VersionCompatibility {
  // supported indicates whether the client version is supported
  bool supported = 1;
  // server_api_version is the API version of the server
  string server_api_version = 2;
  // supported_api_versions lists API versions supported by the server
  repeated string supported_api_versions = 3;
  // server_file_format_version is the file format version of the server
  string server_file_format_version = 4;
  // supported_file_format_versions lists file format versions supported by the server
  repeated string supported_file_format_versions = 5;
  // reason provides human-readable explanation of version incompatibility
  string reason = 6;
}

message SendRequest {
  string topic = 1;
  uint64 message_id = 2;
  bytes body = 3;
  bool batch_mod = 4;
  // version_info contains version information
  VersionInfo version_info = 5;
  // group is the business group associated with this message.
  string group = 6;
  // sender_node is the BanyanDB node name of the sender; set only on the first message of a stream.
  string sender_node = 7;
  // sender_role is the role of the sender node; set only on the first message of a stream.
  string sender_role = 8;
  // sender_tier is the storage tier label of the sender node; set only on the first message of a stream.
  string sender_tier = 9;
}

message SendResponse {
  uint64 message_id = 1;
  string error = 2;
  bytes body = 3;
  model.v1.Status status = 4;
  // version_compatibility contains version compatibility information when status indicates version issues
  VersionCompatibility version_compatibility = 5;
}

message HealthCheckRequest {
  string service_name = 1;
}

message HealthCheckResponse {
  string service_name = 1;
  model.v1.Status status = 2;
  string error = 3;
}

// Chunked Sync Service Messages.
message SyncPartRequest {
  string session_id = 1; // Unique session identifier for this sync operation.
  uint32 chunk_index = 2; // Current chunk index (0-based).
  bytes chunk_data = 4; // Actual chunk data.
  string chunk_checksum = 5; // CRC32 checksum for this chunk.
  repeated PartInfo parts_info = 6; // Information about parts contained in this chunk.

  oneof content {
    SyncMetadata metadata = 7; // Sent with first chunk (chunk_index = 0).
    SyncCompletion completion = 8; // Sent with last chunk to finalize.
  }

  // version_info contains version information
  VersionInfo version_info = 9;
}

// Information about a part contained within a chunk.
message PartInfo {
  uint64 id = 1; // Unique identifier for this part.
  repeated FileInfo files = 2; // Information about individual files within this part.
  uint64 compressed_size_bytes = 3; // Compressed size in bytes from partMetadata.
  uint64 uncompressed_size_bytes = 4; // Uncompressed size in bytes from partMetadata.
  uint64 total_count = 5; // Total count from partMetadata.
  uint64 blocks_count = 6; // Blocks count from partMetadata.
  int64 min_timestamp = 7; // Minimum timestamp from partMetadata.
  int64 max_timestamp = 8; // Maximum timestamp from partMetadata.
  int64 min_key = 9; // Minimum user-provided key for sidx.
  int64 max_key = 10; // Maximum user-provided key for sidx.
  string part_type = 11; // Part type.
}

// Information about an individual file within a part.
message FileInfo {
  string name = 1; // File identifier (e.g., "primary", "timestamps", "tagFamilies:seriesId").
  uint32 offset = 2; // Byte offset within the part where this file starts.
  uint32 size = 3; // Size of this file in bytes.
}

// SyncMetadata contains metadata for the sync operation.
message SyncMetadata {
  string group = 1; // Group name (stream/measure).
  uint32 shard_id = 2; // Shard identifier.
  string topic = 4; // Sync topic (stream-part-sync or measure-part-sync).
  int64 timestamp = 6; // Timestamp when sync started.
  uint32 total_parts = 7; // Total number of parts being synced.
  // sender_node is the BanyanDB node name of the sender.
  string sender_node = 8;
  // sender_role is the role of the sender node.
  string sender_role = 9;
  // sender_tier is the storage tier label of the sender node.
  string sender_tier = 10;
}

// SyncCompletion contains completion information for the sync operation.
message SyncCompletion {
  uint64 total_bytes_sent = 1; // Total bytes sent for validation.
  uint32 total_parts_sent = 2; // Total number of parts sent.
  uint32 total_chunks = 3; // Total number of chunks in this sync.
}

// SyncPartResponse contains the response for a sync part request.
message SyncPartResponse {
  string session_id = 1;
  uint32 chunk_index = 2;
  SyncStatus status = 3;
  string error = 4;
  SyncResult sync_result = 5; // Final result when sync completes.
  // version_compatibility contains version compatibility information when status indicates version issues
  VersionCompatibility version_compatibility = 6;
}

// SyncResult contains the result of a sync operation.
message SyncResult {
  bool success = 1; // Whether entire sync was successful.
  uint64 total_bytes_received = 2; // Total bytes received.
  int64 duration_ms = 3; // Time taken for sync in milliseconds.
  uint32 chunks_received = 4; // Number of chunks successfully received.
  uint32 parts_received = 5; // Number of parts successfully received.
  repeated PartResult parts_results = 6; // Results for each part.
}

// PartResult contains the result for individual parts.
message PartResult {
  bool success = 1; // Whether this part was processed successfully.
  string error = 2; // Error message if processing failed.
  uint32 bytes_processed = 3; // Number of bytes processed for this part.
}

// SyncStatus represents the status of a sync operation.
enum SyncStatus {
  SYNC_STATUS_UNSPECIFIED = 0; // Unspecified status.
  SYNC_STATUS_CHUNK_RECEIVED = 1; // Chunk received and validated successfully.
  SYNC_STATUS_CHUNK_CHECKSUM_MISMATCH = 2; // Chunk checksum validation failed.
  SYNC_STATUS_CHUNK_OUT_OF_ORDER = 3; // Chunk received out of expected order.
  SYNC_STATUS_SESSION_NOT_FOUND = 4; // Session ID not recognized.
  SYNC_STATUS_SYNC_COMPLETE = 5; // Entire sync operation completed successfully.
  SYNC_STATUS_VERSION_UNSUPPORTED = 6; // Version not supported for sync operations.
  SYNC_STATUS_FORMAT_VERSION_MISMATCH = 7; // File format version incompatible.
  SYNC_STATUS_SERVER_BUSY = 8; // Receiver under memory pressure; sender should back off and retry the whole part.
}

service Service {
  rpc Send(stream SendRequest) returns (stream SendResponse);
  rpc HealthCheck(HealthCheckRequest) returns (HealthCheckResponse);
}

// ChunkedSyncService provides streaming sync capabilities for chunked data transfer.
service ChunkedSyncService {
  // SyncPart synchronizes part data using chunked transfer.
  rpc SyncPart(stream SyncPartRequest) returns (stream SyncPartResponse);
}
