syntax = "proto3";

package wix.dealerBackoffice.api.v1;

import "google/api/annotations.proto";
import "google/protobuf/wrappers.proto";
import "google/protobuf/struct.proto";
import "wix/api/callback.proto";

import "wix/api/annotations.proto";
import "wix/api/validations.proto";
import "wix/api/permissions.proto";
import "wix/api/sla.proto";
import "wix/api/api_errors.proto";
import "wix/api/entity.proto";
import "wix/common/query.proto";
import "wix/common/paging.proto";

import "wix/dealerBackoffice/api/v1/offer.proto";
import "wix/personalize/targeting/v1/targeting.proto";

option java_package = "com.wix.dealerBackoffice.api.v1";

// Endpoint responsible for managing key dealer entites — offers.
service OfferService {
  option (wix.api.service_entity).message = "wix.dealerBackoffice.api.v1.Offer";
  option (wix.api.service_maturity) = ALPHA;
  option (wix.api.service_exposure) = INTERNAL;

  // Get single offer
  // GrpcStatus.NOT_FOUND is thrown if requested offer is not found in DB
  rpc GetOffer (GetOfferRequest) returns (GetOfferResponse) {
    option (google.api.http).get = "/v1/dealer/backoffice/offers/{offer_id}";
    option (wix.api.required) = "GetOfferRequest.offer_id";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.READ_OFFER";
    option (wix.api.crud) = {
      method: GET_ITEM
      get_options: {
        id_field: "offer_id",
        item_field: "offer"
      }
    };
  }

  // Get bulk offers
  // No exceptions are thrown if some/all offers were not found.
  // Worst case scenario (no offers are found by provided offerId list) — you get empty offers array.
  rpc GetOffersBulk (GetOffersBulkRequest) returns (GetOffersBulkResponse) {
    option (google.api.http) = {
      post: "/v1/dealer/backoffice/offers/bulk"
      additional_bindings: {
        get: "/v1/dealer/backoffice/offers/bulk"
      }
    };
    option (wix.api.required) = "GetOffersBulkRequest.offer_ids";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.READ_OFFER";
  }

  // Query offers by status/campaign/placement/audience.
  rpc QueryOffers (QueryOffersRequest) returns (QueryOffersResponse) {
    option (google.api.http).post = "/v1/dealer/backoffice/offers/query";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.READ_OFFER";
  }

  rpc CreateOffer (CreateOfferRequest) returns (CreateOfferResponse) {
    option (google.api.http).post = "/v1/dealer/backoffice/offers";
    option (wix.api.required) = "CreateOfferRequest.offer.name";
    option (wix.api.required) = "CreateOfferRequest.offer.asset";
    option (wix.api.required) = "CreateOfferRequest.offer.placement_id";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.CREATE_OFFER";
    option (wix.api.crud) = {
      method: CREATE
      create_options: {
        item_field: "offer"
      }
    };
    option (wix.api.callback) = {
      event_type: CREATED
    };

    option (wix.api.error) = {
      http_code: NOT_FOUND
      application_code: "OFFER_PLACEMENT_NOT_FOUND"
    };

    option (wix.api.error) = {
      http_code: NOT_FOUND
      application_code: "OFFER_CAMPAIAGN_NOT_FOUND"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "PLACEMENT_SLUG_EMPTY"
    };

    option (wix.api.error) = {
      http_code: INTERNAL
      application_code: "TRANSLATOR_API_ERROR"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "PLACEMENT_SCHEMA_MISSING"
    };

    option (wix.api.error) = {
      http_code: INVALID_ARGUMENT
      application_code: "LOCALIZED_CONTENT_ENGLISH_LANGUAGE_MISSING"
    };

    option (wix.api.error) = {
      http_code: INVALID_ARGUMENT
      application_code: "LOCALIZED_CONTENT_NON_ENGLISH_LANGUAGES"
    };

    option (wix.api.error) = {
      http_code: ALREADY_EXISTS
      application_code: "OFFER_SLUG_ALREADY_EXISTS"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "OFFER_SLUG_EMPTY"
    };

    option (wix.api.error) = {
      http_code: NOT_FOUND
      application_code: "UNDER_OFFER_NOT_FOUND"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "UNDER_OFFER_ILLEGAL"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "OFFER_CREATIVE_READ_ONLY"
    };
  }

  rpc DeleteOffer(DeleteOfferRequest) returns (DeleteOfferResponse) {
    option (wix.api.permission).name = "DEALER_BACKOFFICE.UPDATE_OFFER";
    option (google.api.http).delete = "/v1/dealer/backoffice/offers/{offer_id}";
    option (wix.api.required) = "DeleteOfferRequest.offer_id";
  }

  // Full offer update. Fields that are not set will be overwritten with empty values
  rpc UpdateOffer (UpdateOfferRequest) returns (UpdateOfferResponse) {
    option (google.api.http).put = "/v1/dealer/backoffice/offers";
    option (wix.api.required) = "UpdateOfferRequest.offer.guid";
    option (wix.api.required) = "UpdateOfferRequest.offer.name";
    option (wix.api.required) = "UpdateOfferRequest.offer.asset";
    option (wix.api.required) = "UpdateOfferRequest.offer.placement_id";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.UPDATE_OFFER";
    option (wix.api.callback) = {
      event_type: UPDATED
    };

    option (wix.api.error) = {
      http_code: INTERNAL
      application_code: "TRANSLATOR_API_ERROR"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "PLACEMENT_SLUG_EMPTY"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "CREATE_ASSET_AB_TEST_ON_LIVE_OFFER"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "OFFER_CAMPAIGN_UPDATE"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "OFFER_PLACEMENT_UPDATE"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "OFFER_MERGE_ASSET_AB_TEST_WITH_UPDATE"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "MUTATE_ARCHIVED_OFFER"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "PLACEMENT_SCHEMA_MISSING"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "LOCALIZED_CONTENT_ENGLISH_LANGUAGE_MISSING"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "LOCALIZED_CONTENT_NON_ENGLISH_LANGUAGES"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "OFFER_SLUG_EMPTY"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "OFFER_CREATIVE_READ_ONLY"
    };
  }

  // Update offer frequencyCapsConfig. Fields that are not set will be overwritten with empty values
  rpc SetFrequencyCaps (SetFrequencyCapsRequest) returns (SetFrequencyCapsResponse) {
    option (google.api.http).put = "/v1/dealer/backoffice/offers/{offer_id}/frequency-caps";
    option (wix.api.required) = "SetFrequencyCapsRequest.offer_id";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.UPDATE_OFFER";
  }

  // Update offer slug
  rpc UpdateSlug (UpdateSlugRequest) returns (UpdateSlugResponse) {
    option (google.api.http).put = "/v1/dealer/backoffice/offers/{offer_id}/update-slug";
    option (wix.api.required) = "UpdateSlugRequest.offer_id";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.UPDATE_OFFER";
  }

  // Connect offer to campaign and put last in priority
  rpc ConnectCampaign (ConnectCampaignRequest) returns (ConnectCampaignResponse) {
    option (google.api.http).post = "/v1/dealer/backoffice/offers/{offer_id}/connect-campaign";
    option (wix.api.required) = "ConnectCampaignRequest.offer_id";
    option (wix.api.required) = "ConnectCampaignRequest.campaign_id";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.UPDATE_OFFER";


    option (wix.api.error) = {
      http_code: NOT_FOUND
      application_code: "OFFER_CAMPAIAGN_NOT_FOUND"
    };
  }

  // Disconnect offer from campaign and put last in priority
  rpc DisconnectCampaign (DisconnectCampaignRequest) returns (DisconnectCampaignResponse) {
    option (google.api.http).post = "/v1/dealer/backoffice/offers/{offer_id}/disconnect-campaign";
    option (wix.api.required) = "DisconnectCampaignRequest.offer_id";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.UPDATE_OFFER";


    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "OFFER_NOT_CONNECTED_TO_CAMPAIGN"
    };
  }

  // Make offer LIVE
  rpc ActivateOffer (StatusOfferRequest) returns (StatusOfferResponse) {
    option (google.api.http).post = "/v1/dealer/backoffice/offers/{offer_id}/activate";
    option (wix.api.required) = "StatusOfferRequest.offer_id";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.UPDATE_OFFER";

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "MUTATE_ARCHIVED_OFFER"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "ACTIVATE_OFFER_WITHOUT_BRAND_FILTER"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "ACTIVATE_OFFER_WITHOUT_ASSET"
    };
  }

  // Make offer PAUSED
  rpc DeactivateOffer (StatusOfferRequest) returns (StatusOfferResponse) {
    option (google.api.http).post = "/v1/dealer/backoffice/offers/{offer_id}/deactivate";
    option (wix.api.required) = "StatusOfferRequest.offer_id";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.UPDATE_OFFER";


    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "MUTATE_ARCHIVED_OFFER"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "PAUSE_LIVE_OFFER_ASSET_AB_TEST"
    };
  }

  // Make offer ARCHIVED. Warning there's no way to unarchive an offer once it's archived.
  rpc ArchiveOffer (StatusOfferRequest) returns (StatusOfferResponse) {
    option (google.api.http).post = "/v1/dealer/backoffice/offers/{offer_id}/archive";
    option (wix.api.required) = "StatusOfferRequest.offer_id";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.UPDATE_OFFER";
    option (wix.api.callback) = {
      event_type: ACTION
      payload: "wix.dealerBackoffice.api.v1.OfferOperationEvent"
    };
  }

  rpc CopyOffers (CopyOffersRequest) returns (CopyOffersResponse) {
    option (google.api.http).post = "/v1/dealer/backoffice/offers/copy-offers";
    option (wix.api.required) = "CopyOffersRequest.copy_offers_params";
    option (wix.api.required) = "CopyOffersRequest.target_placement_id";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.COPY_OFFERS";
    option (wix.api.sla).response_time_ms = 30000;

    option (wix.api.error) = {
      http_code: INVALID_ARGUMENT
      application_code: "MISSING_REQUIRED_FIELDS"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "SAME_SOURCE_AND_TARGET_PLACEMENT"
    };

  }

  // Make offer IN_REVIEW.
  rpc SubmitOfferForReview (StatusOfferRequest) returns (StatusOfferResponse) {
    option (google.api.http).post = "/v1/dealer/backoffice/offers/{offer_id}/review";
    option (wix.api.required) = "StatusOfferRequest.offer_id";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.UPDATE_OFFER";

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "NOT_PAUSED_OFFER_IN_REVIEW"
    };
  }

  rpc RestoreOffer (StatusOfferRequest) returns (StatusOfferResponse) {
    option (google.api.http).post = "/v1/dealer/backoffice/offers/{offer_id}/restore";
    option (wix.api.required) = "StatusOfferRequest.offer_id";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.UPDATE_OFFER";
  }

  // Change priorities of given offer ids. All offers must belong to same placement.
  rpc PrioritizeOffers (PrioritizeOffersRequest) returns (PrioritizeOffersResponse) {
    option (google.api.http).post = "/v1/dealer/backoffice/offers/prioritize";
    option (wix.api.required) = "PrioritizeOffersRequest.offer_ids";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.UPDATE_OFFER";
    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "OFFER_IN_MORE_THEN_ONE_PLACEMENT"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "PRIORITIZE_ARCHIVED_OFFERS"
    };
  }

  // Convert A/B test asset offer to regular single asset offer
  rpc MergeAssetAbTest (MergeAssetAbTestRequest) returns (MergeAssetAbTestResponse) {
    option (google.api.http).post = "/v1/dealer/backoffice/offers/{offer_id}/merge-asset-abtest";
    option (wix.api.required) = "MergeAssetAbTestRequest.offer_id";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.UPDATE_OFFER";
    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "MERGE_OFFER_ASSET_WITHOUT_AB_TEST"
    };
  }

  // Send offer to translations
  //flynt-disable required-annotation-breaking-change
  rpc SendOfferToTranslation (SendOfferToTranslationRequest) returns (SendOfferToTranslationResponse) {
    option (google.api.http).post = "/v1/dealer/backoffice/offers/{offer_id}/send-to-translation";
    option (wix.api.required) = "SendOfferToTranslationRequest.offer_id";
    option (wix.api.required) = "SendOfferToTranslationRequest.languages";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.UPDATE_OFFER";

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "OFFER_TRANSLATION_PLACEMENT_NOT_TRANSLATABLE"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "OFFER_TRANSLATION_ENGLISH_TRANSLATION_DOES_NOT_EXIST"
    };


    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "OFFER_TRANSLATION_ENGLISH_TRANSLATION_REQUESTED"
    };

    option (wix.api.error) = {
      http_code: FAILED_PRECONDITION
      application_code: "OFFER_CREATIVE_READ_ONLY"
    };
  }

  // List all offers owners ids
  rpc ListOffersOwnersIds (ListOfferOwnersIdsRequest) returns (ListOfferOwnersIdsResponse) {
    option (google.api.http).get = "/v1/dealer/backoffice/offers/owners";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.READ_OFFER";
  };

  // Update offer creative - updates offer's asset.localizedContent only - does not update other asset fields
  rpc UpdateCreative (UpdateCreativeRequest) returns (UpdateCreativeResponse) {
    option (google.api.http).put = "/v1/dealer/backoffice/offers/{offer_id}/update-creative";
    option (wix.api.required) = "UpdateCreativeRequest.offer_id";
    option (wix.api.required) = "UpdateCreativeRequest.creative";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.UPDATE_OFFER";
  }

  // Migrate function to run internal migrations on offers
  rpc Migrate (MigrateRequest) returns (MigrateResponse) {
    option (wix.api.required) = "MigrateRequest.offer_id";
    option (wix.api.permission).name = "DEALER_BACKOFFICE.UPDATE_OFFER";
  }
}

message SendOfferToTranslationRequest {
  string offer_id = 1 [(wix.api.format) = GUID];
  repeated string languages = 2 [(wix.api.format) = LANGUAGE_TAG];
  repeated string localization_managers_ids = 3 [(wix.api.format) = GUID];
  string notes = 4;
}

message SendOfferToTranslationResponse {
}

message GetOfferRequest {
  string offer_id = 1 [(wix.api.format) = GUID];
}

message GetOffersBulkRequest {
  repeated string offer_ids = 1 [(wix.api.format) = GUID];
}

message GetOffersBulkResponse {
  repeated Offer offers = 1;
}

message GetOfferResponse {
  Offer offer = 1;
}

message CreateOfferRequest {
  Offer offer = 1;

  // Optional = default will be to priotize last in placement or if campaign id is passed then last in campaign
  CreateOfferPriorityOverrides priority_overrides = 2;
}

message CreateOfferPriorityOverrides {
  oneof priority_override {
    UnderOffer under_offer = 1;
  }

  message UnderOffer {
    string offer_id = 1  [(wix.api.format) = GUID];
  }
}

message CreateOfferResponse {
  Offer offer = 1;
}

message UpdateOfferRequest {
  Offer offer = 1;
}

message UpdateOfferResponse {
  Offer offer = 1;
}

message UpdateSlugRequest {
  google.protobuf.StringValue offer_id = 1 [(wix.api.format) = GUID, (wix.api.readOnly) = true];
  google.protobuf.StringValue slug = 2 [(wix.api.minLength) = 1];
}

message UpdateSlugResponse {
}


// Supported queries:
//
// filter:
//  query: { filter: { guid: '<uuid>'}}
//  query: { filter: { status: 'ACTIVE'}}
//  query: { filter: { placementId: '<uuid>'}}
//  query: { filter: { placementId: '<uuid>', status: 'DRAFT'}}
//  query: { filter: { campaignId: '<uuid>'}}
//  query: { filter: { campaignId: '<uuid>', status: 'ACTIVE'}}
//  query: { filter: { audienceIds: { $hasSome: ['<uuid>']}}}
//  query: { filter: { createdBy: '<uuid>'}
//  query: { filter: { createdBy: { $in: ['<uuid>', '<uuid>']}}}
//  query: { filter: { updatedBy: '<uuid>'}
//  query: { filter: { updatedBy: { $in: ['<uuid>', '<uuid>']}}}
//  query: { filter: { managersIds: { $hasSome: ['<uuid>']}}}
//  query: { filter: { name: 'exact name' }}
//  query: { filter: { name: { $contains: '<string>'}}}
//  query: { filter: { placementName: 'exact name' }}
//  query: { filter: { placementName: { $contains: '<string>'}}}
//  query: { filter: { placementId: { $in: ['<uuid>']}}}
//  query: { filter: { status: { $in: ['<uuid>']}}}
//  query: { filter: { languages: { $hasSome: ['<uuid>']}}}
//  query: { filter: { inABTest: '<boolean'>}
//  query: { filter: { inABTest: true}
//  query: { filter: { $or: [{ createdBy: '<uuid>' }, { updatedBy: '<uuid>' }, { managersIds: { $hasSome: ['<uuid>', '<uuid>'] }}]}}
/**  query: { filter: {
              $and: [
                {
                  $or: [{ status: OfferStatus.LIVE }, { audienceIds: { $hasSome: ['<uuid>'] } }],
                },
                { createdBy: { $in: ['<uuid>', '<uuid>'] } },
                { placementId: '<uuid>' },
                {
                  $or: [
                    { campaignId: '<uuid>' },
                    { managersIds: { $hasSome: ['<uuid>', '<uuid>'] } },
                  ],
                },
              ],
            },
**/
//
// fields masks:
//  query: { fieldsets: ["relationsOnly"] } — return offer objects projections with only guid, campaignId, placementId props set
//
// By default (no 'fieldsets" provided) full offer objects are returned
//
// paging:
//  query: { paging: { limit: '<int>', offset: '<int>' }}
//
// sort:
//  query: { sort: [ { fieldName: string, order: 'ASC' | 'DESC' } ] }
//  query: { sort: [ { fieldName: 'dateUpdated', order: 'ASC' } ] }
//

message QueryOffersRequest {
  wix.common.Query query = 1;
}

// List of offers returned from query with paging metadata
message QueryOffersResponse {
  repeated Offer offers = 1;
  wix.common.PagingMetadata paging_metadata = 2;
}


message CopyOffersRequest {
  string target_placement_id = 1 [(wix.api.format) = GUID];
  CopyOffersParams copy_offers_params = 2;
}

message CopyOffersResponse {
  repeated FailedOfferCopy failed = 1;
  int32 successful = 2;
}


// Connect an offer to a campagin (and optionally modify offer priority)
message ConnectCampaignRequest {
  string offer_id = 1 [(wix.api.format) = GUID];
  string campaign_id = 2 [(wix.api.format) = GUID];

  // when true priority of an offer in campaign wont change
  // if false or null then offer will become last in campaign
  google.protobuf.BoolValue keep_priority = 3;
}

message ConnectCampaignResponse {
}

// Disconnect an offer from a campagin (and optionally modify offer priority)
message DisconnectCampaignRequest {
  string offer_id = 1 [(wix.api.format) = GUID];

  // when true priority of offer in campaign wont change if false or null then offer will be after last offer in campaign
  google.protobuf.BoolValue keep_priority = 3;
}

message DisconnectCampaignResponse {
}

// Merge a/b test assets to one
message MergeAssetAbTestRequest {
  string offer_id = 1 [(wix.api.format) = GUID];

  // Which asset should be the one - A or B
  AbTestWinner winner = 2;

  enum AbTestWinner {
    UNKNOWN = 0;
    A = 1;
    B = 2;
  }
}

message MergeAssetAbTestResponse {
}

// Request to prioritize offers that belong to the same placement.
// Can contain a subset of the offers and it will keep rest of order in placement
message PrioritizeOffersRequest {
  repeated string offer_ids = 1 [(wix.api.format) = GUID, (wix.api.minSize) = 2];
}

message PrioritizeOffersResponse {
}

// Which offer's status to update
message StatusOfferRequest {
  string offer_id = 1 [(wix.api.format) = GUID];
}

// Current offer calculated status after status update action
message StatusOfferResponse {
  Offer.Status status = 1 [(wix.api.readOnly) = true];
}

// Update offer frequency caps
message SetFrequencyCapsRequest {
  string offer_id = 1 [(wix.api.format) = GUID];
  Offer.FrequencyCapsConfig frequency_caps_config = 2;
}

message SetFrequencyCapsResponse {
  Offer offer = 1;
}

message ListOfferOwnersIdsRequest {
}

message ListOfferOwnersIdsResponse {
  repeated string owner_ids = 1 [(wix.api.format) = GUID];
}

message CopyOffersParams {
  oneof copy_params {
    string source_placement_id = 1 [(wix.api.format) = GUID];
    OffersToCopy offers = 2;
  }
}

message OffersToCopy {
  repeated string offers_ids = 1 [(wix.api.format) = GUID, (wix.api.maxSize) = 500];
}

message FailedOfferCopy {
    string offer_id = 1 [(wix.api.format) = GUID];
}

message DeleteOfferRequest {
  google.protobuf.StringValue offer_id = 1 [(wix.api.format) = GUID, (wix.api.readOnly) = true];
}
message DeleteOfferResponse {}

message UpdateCreativeRequest {
  google.protobuf.StringValue offer_id = 1 [(wix.api.format) = GUID];
  // the creative Struct field is matching the offers asset.localizedContent english content
  google.protobuf.Struct creative = 2;
}

message UpdateCreativeResponse {
  Offer offer = 1;
}

message MigrateRequest {
  // offer id to migrate targeting
  string offer_id = 1 [(wix.api.format) = GUID, (wix.api.readOnly) = true];

  // migrate type -
  MigrateType migrate_type = 2;
  
  enum MigrateType {
    UNKNOWN = 0;
    // TARGETING_V1_MIGRATION - migrate targeting from v1 to v2
    TARGETING_V1_MIGRATION = 1;
    // DYNAMIC_PARAMS_MIGRATION - migrate dynamic params to contain bi level
    DYNAMIC_PARAMS_MIGRATION = 2;
  }

  // Struct payload for migration
  google.protobuf.Struct payload = 3;
}

message MigrateResponse {
}