syntax = "proto3";

package flipt.evaluation;

import "google/protobuf/timestamp.proto";
import "google/api/annotations.proto";
import "google/api/visibility.proto";
import "google/api/field_behavior.proto";
import "gnostic/openapi/v3/annotations.proto";

option go_package = "go.flipt.io/flipt/rpc/flipt/evaluation";

message EvaluationRequest {
  string request_id = 1;
  string namespace_key = 2 [(google.api.field_behavior) = REQUIRED];
  string flag_key = 3 [(google.api.field_behavior) = REQUIRED];
  string entity_id = 4 [(google.api.field_behavior) = REQUIRED];
  map<string, string> context = 5 [(google.api.field_behavior) = REQUIRED];
  string reference = 6;
}

message BatchEvaluationRequest {
  string request_id = 1;
  repeated EvaluationRequest requests = 3 [(google.api.field_behavior) = REQUIRED];
  string reference = 4;
}

message BatchEvaluationResponse {
  string request_id = 1;
  repeated EvaluationResponse responses = 2;
  double request_duration_millis = 3;
}

enum EvaluationReason {
    UNKNOWN_EVALUATION_REASON = 0;
    FLAG_DISABLED_EVALUATION_REASON = 1;
    MATCH_EVALUATION_REASON = 2;
    DEFAULT_EVALUATION_REASON = 3;
}

enum ErrorEvaluationReason {
  UNKNOWN_ERROR_EVALUATION_REASON = 0;
  NOT_FOUND_ERROR_EVALUATION_REASON = 1;
}

enum EvaluationResponseType {
  VARIANT_EVALUATION_RESPONSE_TYPE = 0;
  BOOLEAN_EVALUATION_RESPONSE_TYPE = 1;
  ERROR_EVALUATION_RESPONSE_TYPE = 2;
}

message EvaluationResponse {
    EvaluationResponseType type = 1;
    oneof response {
        BooleanEvaluationResponse boolean_response = 2;
        VariantEvaluationResponse variant_response = 3;
        ErrorEvaluationResponse error_response = 4;
    }
}

message BooleanEvaluationResponse {
  bool enabled = 1;
  EvaluationReason reason = 2;
  string request_id = 3;
  double request_duration_millis = 4;
  google.protobuf.Timestamp timestamp = 5;
  string flag_key = 6;
}

message VariantEvaluationResponse {
  bool match = 1;
  repeated string segment_keys = 2;
  EvaluationReason reason = 3;
  string variant_key = 4;
  string variant_attachment = 5;
  string request_id = 6;
  double request_duration_millis = 7;
  google.protobuf.Timestamp timestamp = 8;
  string flag_key = 9;
}

message ErrorEvaluationResponse {
  string flag_key = 1;
  string namespace_key = 2;
  ErrorEvaluationReason reason = 3;
}

service EvaluationService {
  rpc Boolean(EvaluationRequest) returns (BooleanEvaluationResponse) {
    option (google.api.http) = {post: "/evaluate/v1/boolean" body: "*"};
    option (gnostic.openapi.v3.operation) = {operation_id: "evaluateBoolean"};
  }
  rpc Variant(EvaluationRequest) returns (VariantEvaluationResponse) {
    option (google.api.http) = {post: "/evaluate/v1/variant" body: "*"};
    option (gnostic.openapi.v3.operation) = {operation_id: "evaluateVariant"};
  }
  rpc Batch(BatchEvaluationRequest) returns (BatchEvaluationResponse) {
    option (google.api.http) = {post: "/evaluate/v1/batch" body: "*"};
    option (gnostic.openapi.v3.operation) = {operation_id: "evaluateBatch"};
  }
}

message EvaluationDistribution {
  string id = 1;
  string rule_id = 2;
  string variant_id = 3;
  string variant_key = 4;
  string variant_attachment = 5;
  float rollout = 6;
}

enum EvaluationRolloutType {
  UNKNOWN_ROLLOUT_TYPE = 0;
  SEGMENT_ROLLOUT_TYPE = 1;
  THRESHOLD_ROLLOUT_TYPE = 2;
}

message EvaluationRollout {
  EvaluationRolloutType type = 1;
  int32 rank = 2;
  oneof rule {
    EvaluationRolloutSegment segment = 3;
    EvaluationRolloutThreshold threshold = 4;
  }
}

message EvaluationRolloutThreshold {
  float percentage = 1;
  bool value = 2;
}

enum EvaluationSegmentOperator {
  OR_SEGMENT_OPERATOR = 0;
  AND_SEGMENT_OPERATOR = 1;
}

message EvaluationRolloutSegment {
  bool value = 1;
  EvaluationSegmentOperator segment_operator = 2;
  repeated EvaluationSegment segments = 3;
}

enum EvaluationSegmentMatchType {
  ALL_SEGMENT_MATCH_TYPE = 0;
  ANY_SEGMENT_MATCH_TYPE = 1;
}

message EvaluationSegment {
  string key = 1;
  string name = 2;
  string description = 3;
  EvaluationSegmentMatchType match_type = 4;
  google.protobuf.Timestamp created_at = 5;
  google.protobuf.Timestamp updated_at = 6;
  repeated EvaluationConstraint constraints = 7;
}

message EvaluationVariant {
  string id = 1;
  string key = 2;
  string attachment = 3;
}

enum EvaluationFlagType {
  VARIANT_FLAG_TYPE = 0;
  BOOLEAN_FLAG_TYPE = 1;
}

message EvaluationFlag {
  string key = 1;
  string name = 2;
  string description = 3;
  bool enabled = 4;
  EvaluationFlagType type = 5;
  google.protobuf.Timestamp created_at = 6;
  google.protobuf.Timestamp updated_at = 7;
  repeated EvaluationRule rules = 8;
  repeated EvaluationRollout rollouts = 9;
  optional EvaluationVariant default_variant = 10;
}

enum EvaluationConstraintComparisonType {
  UNKNOWN_CONSTRAINT_COMPARISON_TYPE = 0;
  STRING_CONSTRAINT_COMPARISON_TYPE = 1;
  NUMBER_CONSTRAINT_COMPARISON_TYPE = 2;
  BOOLEAN_CONSTRAINT_COMPARISON_TYPE = 3;
  DATETIME_CONSTRAINT_COMPARISON_TYPE = 4;
  ENTITY_ID_CONSTRAINT_COMPARISON_TYPE = 5;
}

message EvaluationConstraint {
  string id = 1;
  EvaluationConstraintComparisonType type = 2;
  string property = 3;
  string operator = 4;
  string value = 5;
}

message EvaluationRule {
  string id = 1;
  repeated EvaluationSegment segments = 2;
  int32 rank = 3;
  EvaluationSegmentOperator segment_operator = 4;
  repeated EvaluationDistribution distributions = 5;
}

message EvaluationNamespace {
  string key = 1;
}

message EvaluationNamespaceSnapshot {
  EvaluationNamespace namespace = 1;
  repeated EvaluationFlag flags = 2;
}

message EvaluationNamespaceSnapshotRequest {
  string key = 1;
  string reference = 2;
}

service DataService {
  option (google.api.api_visibility) = {restriction: "flipt:sdk:ignore"};

  rpc EvaluationSnapshotNamespace(EvaluationNamespaceSnapshotRequest) returns (EvaluationNamespaceSnapshot);
}
