// flynt-disable boolean-field-name-prefix
// flynt-disable crud-corresponding-emits-validation
// flynt-disable deprecated-callback-event-validation
// flynt-disable disallow-direct-common-imports
// flynt-disable field-lower-snake-case
// flynt-disable invalid-id-name
// flynt-disable missing-array-limits
// flynt-disable missing-field-comments
// flynt-disable missing-permission
// flynt-disable missing-string-validations
// flynt-disable missing-version-in-rest-path-url
// flynt-disable request-response
syntax = "proto3";

package wix.coupons.api.v2;

import "wix/coupons/api/v2/specification.proto";
import "wix/coupons/api/v2/coupon.proto";
import "wix/coupons/api/v2/cart.proto";
import "wix/coupons/api/v2/response-status.proto";
import "wix/common/bulk.proto";
import "google/api/annotations.proto";
import "wix/api/validations.proto";
import "wix/api/annotations.proto";
import "wix/api/callback.proto";
import "google/protobuf/wrappers.proto";
import "google/protobuf/field_mask.proto";
import "wix/api/permissions.proto";
import "wix/api/entity.proto";
import "wix/sdk/definitions.proto";

option java_package = "com.wix.coupons.api.v2";

service CouponsV2 {
    option (wix.api.service_exposure) = PUBLIC;
    option (wix.api.service_maturity) = GA;
    option (wix.api.service_entity).message = "wix.coupons.api.v2.Coupon";

    /* 
    Creates a new coupon.  

    When creating a coupon, the `specification` object must contain values for `name`, `code`, `startTime`, 
    and either `scope` or `minimumSubtotal`. The exception is for a `freeShipping` coupon type, for which you cannot apply 
    a `scope` and `minimumSubtotal` is optional.  

    The coupon `scope` defines the items a coupon applies to. A coupon can apply to all items in a specific Wix application, 
    a group within the application, or a single item within a group. 
    See [valid scope values](https://dev.wix.com/api/rest/coupons/coupons/valid-scope-values).  

    The `specification` object must also contain a value for exactly 1 of the following coupon properties. 
    This defines the coupon type.  
    
    + `"moneyOffAmount"`
    + `"percentOffRate"`
    + `"freeShipping"`
    + `"fixedPriceAmount"`
    + `"buyXGetY"`
    */
    rpc Create (CreateCouponRequest) returns (CreateCouponResponse) {
        option (google.api.http) = {
            post: "/v2/coupons"
            additional_bindings {
                // Needed in order to maintain backwards compatibility
                post: "/api/v2/coupons"
            }
        };
        option (.wix.sdk.signature) = {params: "specification"};
        option (wix.api.permission).name = "COUPONS.MANAGE";

        // Triggered when a coupon is created.
        option (wix.api.callback) = {
            event_type: CREATED
            permission: "COUPONS.MANAGE"
            exposure: PUBLIC
        };
    }

    /* 
    Updates a coupon.  

    Only the properties passed in the `specification` object will be updated. All other properties will remain the same.  
    
    To remove a value from the coupon, pass its corresponding property with a value of `null`.  
    
    When updating a coupon, you cannot change the coupon's `type`. For example, if the coupon's `type` is `moneyOffAmount`, 
    you cannot change it to `fixedPriceAmount`. You can update the coupon type's value. For example, you can change the 
    value of `moneyOffAmount` from `5` to `10`.  

    The coupon `scope` defines the items a coupon applies to. A coupon can apply to all items in a specific Wix application, 
    a group within the application, or a single item within a group. 
    See [valid scope values](https://dev.wix.com/api/rest/coupons/coupons/valid-scope-values).  
    */
    rpc Update (UpdateCouponRequest) returns (UpdateCouponResponse) {
        option (google.api.http) = {
            patch: "/v2/coupons/{id}"
            additional_bindings {
                // Needed in order to maintain backwards compatibility
                patch: "/api/v2/coupons/{id}"
            }
        };
        option (.wix.sdk.signature) = {
            params: "specification"
            params: "fieldMask"
        };
        option (wix.api.permission).name = "COUPONS.MANAGE";

        // Triggered when a coupon specification is updated.
        option (wix.api.callback) = {
            event_type: UPDATED
            permission: "COUPONS.MANAGE"
        };
    }

    // Retrieves a coupon by ID.
    rpc Get (GetCouponRequest) returns (GetCouponResponse) {
        option (google.api.http) = {
            get: "/v2/coupons/{id}"
            additional_bindings {
                // Needed in order to maintain backwards compatibility
                get: "/api/v2/coupons/{id}"
            }
        };

        option (wix.api.permission).name = "COUPONS.MANAGE";

        option (.wix.api.crud) = {
            method: GET_ITEM
            get_options: {
                id_field: 'id'
            }
        };
    }

    // Deletes a coupon.
    rpc Delete (DeleteCouponRequest) returns (DeleteCouponResponse) {
        option (google.api.http) = {
            delete: "/v2/coupons/{id}"
            additional_bindings {
                // Needed in order to maintain backwards compatibility
                delete: "/api/v2/coupons/{id}"
            }
        };

        option (wix.api.permission).name = "COUPONS.MANAGE";

        // Triggered when a coupon is deleted.
        option (wix.api.callback) = {
            event_type: DELETED
            permission: "COUPONS.MANAGE"
        };

        option (.wix.api.crud) = {
            method: DELETE
            delete_options: {
                id_field: "id"
            }
        };
    }

    // Retrieves a list of coupons with pagination and filters.
    // A maximum of 100 coupons will be returned per request.
    rpc Query (QueryCouponsRequest) returns (QueryCouponsResponse) {
        option (google.api.http) = {
            post: "/v2/coupons/query"
            additional_bindings {
                // Needed in order to maintain backwards compatibility
                post: "/api/v2/coupons/query"
            }
        };
        option (.wix.sdk.signature) = {params: "query"};
        option (wix.api.permission).name = "COUPONS.MANAGE";
    }

    // Calculate a cart's total price after applying a coupon.
    // Pass the Cart with line items and shipping, and the cart will be returned
    // along with its coupon's calculations applied.
    rpc CalculateCart (CalculateRequest) returns (CalculateResponse) {
        option (google.api.http) = {
            post: "/api/v2/coupons/codes/{code}/calculate-cart"
            additional_bindings {
                post: "/api/v2/coupons/{id}/calculate-cart"
            }
        };

        option (wix.api.permission).name = "COUPONS.MANAGE";
        option (wix.api.exposure) = INTERNAL;
    }

    // It is the responsibility of the payment process to call this endpoint after
    // the coupon was used.
    rpc IncreaseUsage (IncreaseUsageRequest) returns (IncreaseUsageResponse) {
        option (google.api.http) = {
            post: "/api/v2/coupons/{id}/increase-usage"
        };
        option (wix.api.exposure) = INTERNAL;

        // Triggered when a coupon is applied.
        option (wix.api.callback) = {
            event_type: ACTION
            payload: "wix.coupons.api.v2.CouponApplied"
            permission: "COUPONS.MANAGE"
            exposure: PUBLIC
        };
    }

    // Returns true if the site has ever had any coupons (even if they have all been deleted or deactivated).
    rpc HasCoupons (HasCouponsRequest) returns (HasCouponsResponse) {
        option (google.api.http).get = "/api/v2/coupons/has-coupons";
        option (wix.api.exposure) = INTERNAL;
    }

    // Deletes multiple coupons.
    rpc BulkDeleteCoupons(BulkDeleteCouponsRequest) returns (BulkDeleteCouponsResponse) {
        option (google.api.http) = {
            post: "/v2/bulk/coupons/delete"
        };
        option (.wix.sdk.signature) = {params: "ids"};
        option (wix.api.permission).name = "COUPONS.MANAGE";

        // Triggered when a coupon is deleted.
        option (wix.api.callback) = {
            event_type: DELETED
            permission: "COUPONS.MANAGE"
        };

        option (.wix.api.crud) = {
            method: BULK_DELETE
            bulk_delete_options: {
                ids_field: "ids"
            }
        };
    }

    // Creates multiple coupons.
    rpc BulkCreateCoupons(BulkCreateCouponsRequest) returns (BulkCreateCouponsResponse) {
        option (google.api.http) = {
            post: "/v2/bulk/coupons/create"
        };
        option (.wix.sdk.signature) = {params: "specifications"};
        option (wix.api.permission).name = "COUPONS.MANAGE";

        // Triggered when a coupon is created.
        option (wix.api.callback) = {
            event_type: CREATED
            permission: "COUPONS.MANAGE"
            exposure: PUBLIC
        };

        option (.wix.api.crud) = {
            method: BULK_CREATE
            bulk_create_options: {
                item_field: "specifications"
            }
        };
    }
}

message HasCouponsRequest {
}

message HasCouponsResponse {
    bool has_coupons = 1; // True if site has ever had a coupon.
}


message CreateCouponRequest {
    // Coupon to create.
    Specification specification = 1;
}

message CreateCouponResponse {
    string id = 1; // ID of the newly created coupon.
}

message UpdateCouponRequest {
    string id = 1; // ID of the coupon to update.
    google.protobuf.FieldMask fieldMask = 3; // Field mask of fields to update (required - passing an empty `fieldMask` will return an error). Valid field masks are any of those in the `specification` field. 
    Specification specification = 2; // Coupon information to update.
}

message UpdateCouponResponse {
}

message GetCouponRequest {
    string id = 1; // ID of the coupon to retrieve.
}

message GetCouponResponse {
    Coupon coupon = 1; // Retrieved coupon.
}

message QueryCouponsRequest {
    Query query = 1;
}

message QueryCouponsResponse {
    repeated Coupon coupons = 1; // Returned coupons.
    google.protobuf.Int32Value total_results = 3; // Total results.
}

message CalculateRequest {
    oneof CalculateBy {
        string id = 1; // For calculating by coupon ID (usually for cart calculate phase).
        string code = 2; // For calculating by coupon code (usually for apply coupon phase - for validation).
        Specification discount = 3; // Type of in-memory discount that can be applied when coupon doesn't exist.
    }
    Cart cart = 10; // Cart to which the coupon will be applied.
    string currency_symbol = 20; // Currency symbol for error message and applied coupon.
    google.protobuf.Int32Value precision = 21; // Round the result to <precision> places after the decimal dot. Defaults to 2 if not provided.
    google.protobuf.StringValue unique_user_identifier = 22; // Unique identifier of a buyer that applied the coupon. Used to limit coupon use per customer.
}

message CalculateResponse {
    message AppliedCoupon {
        string name = 1; // Name of the coupon applied.
        string id = 3; // Coupon ID.
        string code = 4; // Coupon code.
        bool is_free_shipping = 5; // Whether the coupon type entitles free shipping.
        string coupon_type = 6; // Coupon type (e.g., moneyOffAmount, buyXGetY, percentOffRate).
        string discount_value = 7; // Discount value (e.g., $10, 10%).
        google.protobuf.Int32Value discounted_cycle_count = 8; // Amount of discounted cycles for subscription item. None specifies for all cycles.
    }
    Cart cart = 1; // Cart after applying the coupon.
    AppliedCoupon applied_coupon = 2; // Applied coupon information.
    repeated Error error = 10; // Errors, in case call failed.
}

message IncreaseUsageRequest {
    string id = 1; // Coupon ID.
    google.protobuf.StringValue used_by = 2; // Unique ID of the entity that the coupon was applied to (e.g., orderId).
    google.protobuf.StringValue unique_user_identifier = 3; // Unique identifier of a buyer that applied the coupon. Used to limit coupon use per customer.
    google.protobuf.StringValue wix_app_id = 4 [(wix.api.format) = GUID]; // ID of app that applied the coupon (e.g. bookings appDefId).
}

message IncreaseUsageResponse {
    repeated Error error = 10; // Errors, in case call failed.
}


message DeleteCouponRequest {
    string id = 1; // ID of the coupon to delete.
}

message DeleteCouponResponse {
}

message BulkDeleteCouponsRequest {
    // IDs of coupons to delete.
    repeated string ids = 1 [(wix.api.maxLength) = 100, (wix.api.format) = GUID];
}

message BulkDeleteCouponsResponse {
    // Item metadata.
    repeated wix.common.ItemMetadata results = 1;
    // Bulk action metadata.
    wix.common.BulkActionMetadata delete_metadata = 2;
}

message BulkCreateCouponsRequest {
    // List of coupon specifications to be created.
    repeated Specification specifications = 1 [(wix.api.minSize) = 1, (wix.api.maxSize) = 100];
    /* 
    Whether to return full coupon entity in the response.  
    
    Default: `false`
    */
    bool return_full_entity = 2;
}

message BulkCreateCouponsResponse {
    // Items created by bulk action.
    repeated BulkCreateCouponResult results = 1;
    // Bulk action metadata.
    wix.common.BulkActionMetadata bulk_action_metadata = 2;
}

message BulkCreateCouponResult {
    // Item metadata.
    wix.common.ItemMetadata item_metadata = 1;
    // New coupons.
    Coupon coupon = 2;
}

message Query {
    // Optional pagination parameters
    Paging paging = 1;
    // Filter string (e.g., when {"expired":"true"}, expired coupons will be returned).
    google.protobuf.StringValue filter = 2;
    // Sort string.
    google.protobuf.StringValue sort = 3;
}

message Paging {
    // Number of items to load.
    google.protobuf.Int32Value limit = 1 [(wix.api.min) = 0, (wix.api.max) = 100];
    // Offset since the beginning of the collection.
    google.protobuf.Int32Value offset = 2 [(wix.api.min) = 0];
}

message PagingMetadata {
    // Requested number of items to load.
    int32 items = 1;
    // Requested offset since the beginning of the collection.
    int32 offset = 2;
}
