syntax = "proto3";

package aduib.rpc.v2;

import "google/protobuf/struct.proto";

option go_package = "github.com/aduib/rpc/v2;rpcv2";
option java_package = "com.aduib.rpc.v2";
option java_multiple_files = true;

// ============================================================
// 核心消息
// ============================================================

message Request {
  // 协议版本
  string aduib_rpc = 1;  // "2.0"

  // 请求标识
  string id = 2;

  // 路由
  string method = 3;
  optional string name = 4;

  // 负载
  google.protobuf.Struct data = 5;

  // 链路追踪
  optional TraceContext trace_context = 6;

  // 元数据
  optional RequestMetadata metadata = 7;

  // QoS
  optional QosConfig qos = 8;
}

message Response {
  // 协议版本
  string aduib_rpc = 1;

  // 请求标识
  string id = 2;

  // 状态
  ResponseStatus status = 3;

  // 结果（二选一）
  oneof payload {
    google.protobuf.Value result = 4;
    RpcError error = 5;
  }

  // 链路追踪
  optional TraceContext trace_context = 6;

  // 元数据
  optional ResponseMetadata metadata = 7;
}

enum ResponseStatus {
  RESPONSE_STATUS_UNSPECIFIED = 0;
  RESPONSE_STATUS_SUCCESS = 1;
  RESPONSE_STATUS_ERROR = 2;
  RESPONSE_STATUS_PARTIAL = 3;
}

// ============================================================
// 错误
// ============================================================

message RpcError {
  int32 code = 1;
  string name = 2;
  string message = 3;
  repeated ErrorDetail details = 4;
  optional DebugInfo debug = 5;
}

message ErrorDetail {
  string type = 1;
  optional string field = 2;
  string reason = 3;
  map<string, string> metadata = 4;
}

message DebugInfo {
  optional string stack_trace = 1;
  optional string internal_message = 2;
  int64 timestamp_ms = 3;
}

// ============================================================
// 链路追踪
// ============================================================

message TraceContext {
  string trace_id = 1;
  string span_id = 2;
  optional string parent_span_id = 3;
  bool sampled = 4;
  map<string, string> baggage = 5;
}

// ============================================================
// 元数据
// ============================================================

message RequestMetadata {
  int64 timestamp_ms = 1;
  optional string client_id = 2;
  optional string client_version = 3;
  optional AuthContext auth = 4;
  optional string tenant_id = 5;
  map<string, string> headers = 9;
  optional bool long_task = 10;
  optional string long_task_method = 11;
  optional int32 long_task_timeout = 12;
}

message ResponseMetadata {
  int64 timestamp_ms = 1;
  int64 duration_ms = 2;
  optional string server_id = 3;
  optional string server_version = 4;
}

message AuthContext {
  AuthScheme scheme = 1;
  optional string credentials = 2;
  optional string principal = 3;
  repeated string roles = 4;
}

enum AuthScheme {
  AUTH_SCHEME_UNSPECIFIED = 0;
  AUTH_SCHEME_BEARER = 1;
  AUTH_SCHEME_API_KEY = 2;
  AUTH_SCHEME_MTLS = 3;
}

// ============================================================
// QoS
// ============================================================

message QosConfig {
  Priority priority = 1;
  optional int64 timeout_ms = 2;
  optional RetryConfig retry = 3;
  optional string idempotency_key = 4;
}

enum Priority {
  PRIORITY_UNSPECIFIED = 0;
  PRIORITY_LOW = 1;
  PRIORITY_NORMAL = 2;
  PRIORITY_HIGH = 3;
  PRIORITY_CRITICAL = 4;
}

message RetryConfig {
  int32 max_attempts = 1;
  int64 initial_delay_ms = 2;
  int64 max_delay_ms = 3;
  double backoff_multiplier = 4;
  repeated int32 retryable_codes = 5;
}

enum HealthStatus {
  HEALTH_STATUS_UNSPECIFIED = 0;
  HEALTH_STATUS_HEALTHY = 1;
  HEALTH_STATUS_UNHEALTHY = 2;
  HEALTH_STATUS_DEGRADED = 3;
  HEALTH_STATUS_UNKNOWN = 4;
}

// ============================================================
// 任务
// ============================================================

message TaskRecord {
  string task_id = 1;
  optional string parent_task_id = 2;
  TaskStatus status = 3;
  Priority priority = 4;
  int64 created_at_ms = 5;
  optional int64 scheduled_at_ms = 6;
  optional int64 started_at_ms = 7;
  optional int64 completed_at_ms = 8;
  int32 attempt = 9;
  int32 max_attempts = 10;
  optional int64 next_retry_at_ms = 11;
  optional google.protobuf.Value result = 12;
  optional RpcError error = 13;
  optional TaskProgress progress = 14;
  map<string, string> metadata = 15;
  repeated string tags = 16;
}

enum TaskStatus {
  TASK_STATUS_UNSPECIFIED = 0;
  TASK_STATUS_PENDING = 1;
  TASK_STATUS_SCHEDULED = 2;
  TASK_STATUS_RUNNING = 3;
  TASK_STATUS_SUCCEEDED = 4;
  TASK_STATUS_FAILED = 5;
  TASK_STATUS_CANCELED = 6;
  TASK_STATUS_RETRYING = 7;
}

message TaskProgress {
  int64 current = 1;
  int64 total = 2;
  optional string message = 3;
  optional double percentage = 4;
}

message TaskSubmitRequest {
  string target_method = 1;
  optional google.protobuf.Struct params = 2;
  Priority priority = 3;
}

message TaskSubmitResponse {
  string task_id = 1;
  TaskStatus status = 2;
  int64 created_at_ms = 3;
}

message TaskQueryRequest {
  string task_id = 1;
}

message TaskQueryResponse {
  TaskRecord task = 1;
}

message TaskCancelRequest {
  string task_id = 1;
  optional string reason = 2;
}

message TaskCancelResponse {
  string task_id = 1;
  TaskStatus status = 2;
  bool canceled = 3;
}

message TaskSubscribeRequest {
  string task_id = 1;
  repeated string events = 2;
}

message TaskEvent {
  string event = 1;
  TaskRecord task = 2;
  int64 timestamp_ms = 3;
}

// ============================================================
// 健康检查
// ============================================================

message HealthCheckRequest {
  optional string service = 1;
}

message HealthCheckResponse {
  HealthStatus status = 1;
  map<string, HealthStatus> services = 2;
}

// ============================================================
// 服务定义
// ============================================================

service AduibRpcService {
  // 一元调用
  rpc Call(Request) returns (Response);

  // 服务端流式
  rpc CallServerStream(Request) returns (stream Response);

  // 客户端流式
  rpc CallClientStream(stream Request) returns (Response);

  // 双向流式
  rpc CallBidirectional(stream Request) returns (stream Response);
}

service TaskService {
  // 提交任务
  rpc Submit(TaskSubmitRequest) returns (TaskSubmitResponse);

  // 查询任务
  rpc Query(TaskQueryRequest) returns (TaskQueryResponse);

  // 取消任务
  rpc Cancel(TaskCancelRequest) returns (TaskCancelResponse);

  // 订阅任务事件
  rpc Subscribe(TaskSubscribeRequest) returns (stream TaskEvent);
}

service HealthService {
  rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
  rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse);
}
