syntax = "proto2";

package wix.spi;

import "google/protobuf/descriptor.proto";
import "wix/spi/http_error_status.proto";

option java_multiple_files = true;
option java_outer_classname = "DefinitionsProto";
option java_package = "com.wix.spi";

/**
Example SPI proto files:

syntax = "proto3";

package com.wixpress.ecom.couponsSpi;

// this service is bla bla bla...
//
// changelog:
// revision 2: added couponGenerated event
service CouponsProvider {
 // since this is an SPI interface definition, the FQDN of the service_entity must start with `wix.interfaces.*`
 option (.wix.spi.service) = {
   fqdn: "wix.interfaces.ecom.v1.coupons_provider" // must be `wix.interfaces.*` for entities that define SPI
   spi_identifier: "com.wixpress.appservice.api.ComponentType.AUTOMATION_TRIGGER"
   config_message: "com.wixpresss.ecom.CouponsProviderConfig"
   host_service: "com.wixpress.ecom.couponsSpi.CouponsSpiHost"
   business_manager_url: "/ecom/coupons" // used to provide deep-link to biz-mgr to finish configuration after code publish in Velo
 };

 // The provider has to send this event when a coupon is generated on the provider system.
 // When the coupon code will be used by a user during checkout,
 // wix-ecom will call the provider in order to calculate the effect of the coupon on the cart
 option (.wix.spi.event) = {
   method_name: "CouponGenerated" // Name of the method on the SPI-Host service that needs to be called. Together with `host_service` annotation above, you can get the full FQN
 };

 // called when the system has to calculate how a coupon affects a given cart
 rpc CalculateCart (CalculateCartRequest) returns (CalculateCartResponse) {
   option (google.api.http) = {
     post: "/calculate-cart"
   };
   option (.wix.spi.error) = {
     name: "CouponNotSupportedError"
     http_code: INVALID_ARGUMENT
     application_code: "COUPON_TYPE_NOT_SUPPORTED"
     data: "com.wixpress.ecom.couponsSpi.TypeNotSupportedError"
   };
 }

 // called when a coupon is applied during checkout and has to be reserved until the checkout is completed
 // redeem will later be called using the reservation_code returned by this method
 rpc Reserve (ReserveCouponRequest) returns (ReserveCouponResponse) {
   option (google.api.http) = {
     post: "/reserve"
   };
 }

 // called after a successful transaction that used a coupon was made, in order to notify the coupons provider
 // that the coupon was redeemed.
 // sends the reservation_code that the was returned by reserve method
 rpc Redeem (RedeemCouponRequest) returns (RedeemCouponResponse) {
   option (google.api.http) = {
     post: "/redeem"
   };
 }

 // called in order to extend coupon expiration date
 // this method was added later than other methods and therefore needs to be toggled in config_message
 rpc ExtendCoupon (ExtendCouponRequest) returns (ExtendCouponResponse) {
   option (google.api.http) ={
     post: "/extend-coupon"
   };
   option (.wix.spi.feature_toggle) = "toggle_extend_coupon_enabled";
 }
}

message CouponsProviderConfig {
 string base_uri = 1 [(.wix.spi.base_uri) = true]; // the base URI where all the methods are deployed. E.g. "https://golden-coupons.com/wix-provider"
 repeated string supported_coupon_types = 2; // specific field related to this SPI
 bool toggle_extend_coupon_enabled = 3; // feature toggle initialized with default value = false. should be true if implemented by spi provider
}

message TypeNotSupportedError {
  string type = 1; The received type that is not supported by the service
}

// =========== another file, standard proto, no SPI annotation ================

service CouponsSpiHost {
 // we cannot use the same service_entity as the SPI definition, because it is only interface definition. Here we need concrete FQDN
 option (.wix.api.service_entity).message = "com.wixpress.ecom.couponsProviderGateway";

 // The provider has to send this event when a coupon is generated on the provider system.
 // When the coupon code will be used by a user during checkout,
 // wix-ecom will call the provider in order to calculate the effect of the coupon on the cart
 rpc CouponGenerated (CouponGeneratedRequest) returns (CouponGeneratedResponse) {
   option (google.api.http) = {
     post: "/v1/coupon-generated"
   };
 }

 // The following 3 methods are an implementation of the SPI interface

 rpc CalculateCart (CalculateCartRequest) returns (CalculateCartResponse) {
   option (google.api.http) = {
     post: "/calculate-cart"
   };
 }

 rpc Reserve (ReserveCouponRequest) returns (ReserveCouponResponse) {
   option (google.api.http) = {
     post: "/reserve"
   };
 }

 rpc Redeem (RedeemCouponRequest) returns (RedeemCouponResponse) {
   option (google.api.http) ={
     post: "/redeem"
   };
 }

 rpc ExtendCoupon (ExtendCouponRequest) returns (RedeemCouponResponse) {
   option (google.api.http) ={
     post: "/extend-coupon"
   };
 }

}

message CouponsProviderGateway {
  option (.wix.api.entity) = {
    fqdn: "wix.gateways.ecom.v1.coupons_provider_gateway"
    implements: "wix.intefaces.ecom.v1.coupons_provider"
  };
}
**/

extend google.protobuf.ServiceOptions {
  optional Service service = 65000;
  repeated Event event = 65001; // spi event is essentially an endpoint that will get requests from spi implementor
}

extend google.protobuf.FieldOptions {
  optional bool base_uri = 65020; // holds the base URI of the implementing service for this spi. (can be https://... | grpc://... | velo:///...)
}

extend google.protobuf.MethodOptions {
  repeated Error error = 65040; // errors that can be thrown by the method
  optional string feature_toggle = 65041; // name of the controlling feature toggle boolean field as it appears in the config message
}

message Service {
  required string spi_identifier = 1; // string representation of dev-center's catalog [ComponentType](https://github.com/wix-private/devcenter/blob/master/app-service/app-service-api/src/main/proto/components_catalog/components_catalog_type.proto)
  required string config_message = 2; // FQN ref to message with config details
  optional string host_service = 3; // FQN ref to proto service of SPI host that implements endpoints that the provider needs to call
  optional string business_manager_url = 4; // relative deeplink to business-manager page where the user needs to continue configuration of current spi
  optional string fqdn = 5; // may be used to define an FQDN directly on SPI service without having a main entity. must start with `wix.interfaces.*`
  optional string app_id = 6; // SPI Host's App Id
  repeated ServiceAppendix appendix_files = 7; // declare external configuration info
}

message ServiceAppendix {
  enum Type {
    UNKNOWN_APPENDIX_TYPE = 0;
    AUTO_VELO = 1 [deprecated = true]; // auto velo configuration
    DOCS_CONF = 2; // wix docs configuration: `documentation.yaml`
    MULTILINGUAL = 3; // wix multilingual configuration
    SEARCH = 4; // nile search configuration
    AUTO_SDK = 5; // auto sdk configuration 
  }
  required Type type = 1; // appendix type
  required string path = 2; // absolute from module root
}

message Error {
  required string name = 1; // name that can be used by SDKs to generate error class
  required HttpStatusCode http_code = 2; // HTTP status code that will be returned with this type of error
  required string application_code = 3; // a constant string in the format of ALL_CAPS that describes the specific error type
  optional string data = 4; // FQN of a message that describes structured data that should be provided in the error body
}

message Event {
  required string method_name = 1; // name of the implemented method in SPI host service. Together with `host_service` annotation above, you can get the full FQN
}
