syntax = "proto3";

package pdrs.admin.v1;

import "google/protobuf/timestamp.proto";

service Admin {
  rpc Drain(DrainRequest) returns (DrainResponse);
  rpc TransferPrimary(TransferPrimaryRequest) returns (TransferPrimaryResponse);
  rpc ValidateConfig(ValidateConfigRequest) returns (ValidateConfigResponse);
  rpc ApplyConfig(ApplyConfigRequest) returns (ApplyConfigResponse);
  rpc GetGroupState(GetGroupStateRequest) returns (GetGroupStateResponse);
  rpc SetLogLevel(SetLogLevelRequest) returns (SetLogLevelResponse);
  rpc ConfigHistoryDiff(ConfigHistoryDiffRequest) returns (ConfigHistoryDiffResponse);
}

message DrainRequest {
  string request_id = 1;
  uint64 timeout_ms = 2;
}

message DrainResponse {
  enum State {
    STATE_UNSPECIFIED = 0;
    DRAINING = 1;
    DRAINED = 2;
    TIMEOUT = 3;
  }

  State state = 1;
  uint32 remaining_primaries = 2;
  repeated uint32 remaining_group_ids = 3;
  string message = 4;
}

message TransferPrimaryRequest {
  string request_id = 1;
  repeated uint32 group_ids = 2;
  string target_member_id = 3;
}

message TransferPrimaryResult {
  enum Status {
    STATUS_UNSPECIFIED = 0;
    SUCCESS = 1;
    SKIPPED_NOT_PRIMARY = 2;
    FAILED = 3;
  }

  uint32 group_id = 1;
  Status status = 2;
  string message = 3;
}

message TransferPrimaryResponse {
  repeated TransferPrimaryResult results = 1;
}

message ValidateConfigRequest {
  string request_id = 1;
  map<string, string> proposed_config = 2;
}

message ConfigViolation {
  string code = 1;
  string message = 2;
}

message ValidateConfigResponse {
  bool accepted = 1;
  repeated ConfigViolation violations = 2;
  map<string, string> normalized_config = 3;
  string apply_mode = 4;
  uint64 candidate_epoch = 5;
}

message ApplyConfigRequest {
  string request_id = 1;
  map<string, string> proposed_config = 2;
  string reason = 3;
}

message ApplyConfigResponse {
  bool accepted = 1;
  repeated ConfigViolation violations = 2;
  map<string, string> active_config = 3;
  uint64 active_epoch = 4;
  string apply_mode = 5;
  string message = 6;
}

message GetGroupStateRequest {
  uint32 group_id = 1;
}

message TimestampParts {
  int64 physical = 1;
  int64 logical = 2;
}

message PrefetchStatus {
  string state = 1;
  google.protobuf.Timestamp last_attempt = 2;
  string last_error = 3;
}

message GroupState {
  bool is_primary = 1;
  int64 in_memory_physical = 2;
  int64 in_memory_logical = 3;
  string actor_state = 4;
  int64 lease_id = 5;
  int64 lease_expire_at_ms = 6;
  int64 last_persisted_physical = 7;
  int64 last_persisted_logical = 8;
  uint32 mailbox_depth = 9;
  uint32 in_flight_requests = 10;
  int64 prefetch_window_start_physical = 11;
  int64 prefetch_window_end_physical = 12;
  google.protobuf.Timestamp lease_expiration_time = 13;
  TimestampParts in_memory_timestamp = 14;
  TimestampParts last_persisted_timestamp = 15;
  uint32 mailbox_size = 16;
  uint32 mailbox_capacity = 17;
  PrefetchStatus prefetch_status = 18;
}

message GetGroupStateResponse {
  GroupState state = 1;
}

message SetLogLevelRequest {
  string request_id = 1;
  string target = 2;
  string level = 3;
}

message SetLogLevelResponse {
  bool success = 1;
  string message = 2;
}

message ConfigHistoryDiffRequest {
  map<string, string> diff_with_active = 1;
  uint32 limit = 2;
}

message ConfigDiffEntry {
  string key = 1;
  string old_value = 2;
  string new_value = 3;
}

message ConfigHistoryItem {
  uint64 epoch = 1;
  string applied_at = 2;
  string reason = 3;
  map<string, string> config = 4;
}

message ConfigHistoryDiffResponse {
  repeated ConfigDiffEntry diff = 1;
  repeated ConfigHistoryItem history = 2;
}
