syntax = "proto3";

package wix.personalize.optimization_test.v1;
option java_package = "com.wixpress.personalize.optimization.test.v1";

import "google/api/annotations.proto";
import "wix/api/annotations.proto";
import "wix/api/callback.proto";
import "wix/api/entity.proto";
import "wix/api/permissions.proto";
import "wix/api/validations.proto";
import "wix/personalize/optimization_test/v1/upstream/wix/common/paging.proto";
import "wix/personalize/optimization_test/v1/test.proto";
import "wix/personalize/optimization_test/v1/upstream/wix/common/query.proto";
import "google/protobuf/wrappers.proto";

/**
  Manages Optimization Tests
 */
service OptimizationTesterService {
  option (wix.api.service_maturity) = ALPHA;
  option (wix.api.service_exposure) = PUBLIC;
  option (wix.api.service_entity).message = "wix.personalize.optimization_test.v1.Test";

  // Internal event, triggered when Test is stopped.
  option (wix.api.event) = {
    topic: "test-stopped-event"
    segment: USERS
    exposure: INTERNAL
    payload: "wix.personalize.optimization_test.v1.TestStoppedEvent"
  };

  /**
    Creates an Optimization Test.

    The request body must include Variants and Kpis. DurationInDays is optional.
   */
  rpc CreateTest (CreateTestRequest) returns (CreateTestResponse) {
    option (google.api.http).post = "/v1/tests";
    option (wix.api.permission).name = "PERSONALIZE.CREATE_OPTIMIZE_TEST";
    option (wix.api.required) = "CreateTestRequest.test";
    option (wix.api.required) = "CreateTestRequest.test.variants";
    option (wix.api.required) = "CreateTestRequest.test.kpis";
    option (wix.api.required) = "CreateTestRequest.test.exposure_id";
    option (wix.api.required) = "CreateTestRequest.test.created_by";
    option (wix.api.crud) = {
      method: CREATE
      create_options: {
        item_field: "test"
      }
    };
    option (wix.api.emits) = {
      event_type: CREATED
    };
  }

  /**
    Retrieves a Test.
   */
  rpc GetTest (GetTestRequest) returns (GetTestResponse) {
    option (google.api.http).get = "/v1/tests/{test_id}";
    option (wix.api.permission).name = "PERSONALIZE.READ_OPTIMIZE_TEST";
    option (wix.api.required) = "GetTestRequest.test_id";
    option (wix.api.crud) = {
      method: GET_ITEM
      get_options: {
        id_field: "test_id"
      }
    };
  }

  /**
  Updates a Test.


  Each time the Test is updated,
  `revision` increments by 1.
  The current `revision` must be passed when updating the Test.
  This ensures you're working with the latest Test
  and prevents unintended overwrites.
   */
  // flynt-disable update-missing-inferred-fieldmask
  rpc UpdateTest (UpdateTestRequest) returns (UpdateTestResponse) {
    option (google.api.http).patch = "/v1/tests/{test.id}";
    option (wix.api.permission).name = "PERSONALIZE.UPDATE_OPTIMIZE_TEST";
    option (wix.api.required) = "UpdateTestRequest.test";
    option (wix.api.required) = "UpdateTestRequest.test.id";
    option (wix.api.required) = "UpdateTestRequest.test.revision";
    option (wix.api.emits) = {
      event_type: UPDATED
    };
    option (wix.api.crud) = {
      method: UPDATE
      update_options: {
        item_field: "test"
      }
    };
  }

  /**
    Deletes a Test.
   */
  rpc DeleteTest (DeleteTestRequest) returns (DeleteTestResponse) {
    option (google.api.http).delete = "/v1/tests/{test_id}";
    option (wix.api.permission).name = "PERSONALIZE.DELETE_OPTIMIZE_TEST";
    option (wix.api.required) = "DeleteTestRequest.test_id";
    option (wix.api.emits) = {
      event_type: DELETED
    };
    option (wix.api.crud) = {
      method: DELETE
      delete_options: {
        id_field: "test_id"
      }
    };
  }

  /**
    Retrieves a list of Tests, given the provided [paging, filtering, and sorting][1].

    Up to 1,000 Tests can be returned per request.
   */
  rpc QueryTests (QueryTestsRequest) returns (QueryTestsResponse) {
    option (google.api.http) = {
      post: "/v1/tests/query"
      additional_bindings : {
        get: "/v1/tests/query";
      }
    };
    option (wix.api.permission).name = "PERSONALIZE.READ_OPTIMIZE_TEST";
    option (wix.api.crud) = {
      method: QUERY
      query_options: {
        items_field: 'tests'
      }
    };
  }

  /**
  Starts a Test.

  Starting the Test in Petri.
 */
  rpc StartTest (StartTestRequest) returns (StartTestResponse) {
    option (google.api.http).post = "/v1/tests/{test_id}/start";
    option (wix.api.permission).name = "PERSONALIZE.UPDATE_OPTIMIZE_TEST";
    option (wix.api.required) = "StartTestRequest.test_id";
    option (wix.api.emits) = {
      event_type: UPDATED
    };
  }

  /**
    Stops a Test.

    Stopping the Test in Petri.
   */
  rpc StopTest (StopTestRequest) returns (StopTestResponse) {
    option (google.api.http).post = "/v1/tests/{test_id}/stop";
    option (wix.api.permission).name = "PERSONALIZE.UPDATE_OPTIMIZE_TEST";
    option (wix.api.required) = "StopTestRequest.test_id";
    option (wix.api.emits) = {
      event_type: UPDATED
    };
  }

  /**
    Set time left to test
   */
  rpc SetTimeLeft (SetTimeLeftRequest) returns (SetTimeLeftResponse) {
    option (google.api.http).put = "/v1/tests/{test_id}/time-left";
    option (wix.api.permission).name = "PERSONALIZE.UPDATE_OPTIMIZE_TEST";
    option (wix.api.required) = "SetTimeLeftRequest.test_id";
    option (wix.api.required) = "SetTimeLeftRequest.time_left_in_days";
  }

}

message CreateTestRequest {
  // The Test to create.
  Test test = 1;
}

message CreateTestResponse {
  // The created Test.
  Test test = 1;
}

message GetTestRequest {
  // ID of the Test to retrieve.
  string test_id = 1 [(wix.api.format) = GUID];
}

message GetTestResponse {
  // The requested Test.
  Test test = 1;
}

message UpdateTestRequest {
  // Test to be updated, may be partial.
  Test test = 1;
}

message UpdateTestResponse {
  // Updated Test.
  Test test = 1;
}

message DeleteTestRequest {
  // Id of the Test to delete.
  string test_id = 1 [(wix.api.format) = GUID];
}

message DeleteTestResponse {}

message QueryTestsRequest {
  // WQL expression.
  wix.personalize.optimization_test.v1.upstream.wix.common.CursorQuery query = 1;
}

message QueryTestsResponse {
  // List of Tests.
  repeated Test tests = 1;

  // Paging metadata
  wix.personalize.optimization_test.v1.upstream.wix.common.CursorPagingMetadata paging_metadata = 2;
}

message StartTestRequest {
  // Id of the Test to start.
  string test_id = 1 [(wix.api.format) = GUID];
}

message StartTestResponse {
  // Updated Test.
  Test test = 1;
}

message StopTestRequest {
  // Id of the Test to stop.
  string test_id = 1 [(wix.api.format) = GUID];
}

message StopTestResponse {
  // Updated Test.
  Test test = 1;
}

message SetTimeLeftRequest {
  // Test id to be updated.
  string test_id = 1 [(wix.api.format) = GUID];

  // The days left for the test to run from this moment.
  int32 time_left_in_days = 2;
}

message SetTimeLeftResponse {
  // Updated Test.
  Test test = 1;
}

message TestStoppedEvent {
  // Id of the Test to stop.
  string test_id = 1 [(wix.api.format) = GUID];
  // The experiment id in Petri.
  google.protobuf.StringValue experiment_id = 2 [(wix.api.format) = GUID,
    deprecated = true,
    (.wix.api.field_deprecated) = {replaced_by: "ab_test_id", target_removal_date: "2025-12-30"}
  ];
  // The stop time.
  google.protobuf.Int32Value stop_time = 3;
  // The stop reason.
  StopReason stop_reason = 4;
  // The user triggering the stop.
  google.protobuf.StringValue stopped_by = 5 [(wix.api.format) = GUID];
  // The a/b test id in Petri.
  google.protobuf.StringValue ab_test_id = 6 [(wix.api.maxLength) = 60];

  enum StopReason {
    UNKNOWN_STOP_REASON = 0;
    BY_USER = 1;
    BY_DURATION_EXPIRED = 2;
  }
}