@vipros-org/sdk 3.0.1 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -30,9 +30,9 @@ No npm install required. Add this to your HTML:
30
30
  <script src="https://cdn.jsdelivr.net/npm/@vipros-org/sdk@latest/vipros-sdk.min.js"></script>
31
31
 
32
32
  <script>
33
- ViprosSDK.init({
34
- apiKey: 'your-api-key'
35
- });
33
+ ViprosSDK.init({
34
+ apiKey: "your-api-key",
35
+ });
36
36
  </script>
37
37
 
38
38
  <vipros-offer-card ean="4007123684731" price="89.99"></vipros-offer-card>
@@ -41,21 +41,8 @@ No npm install required. Add this to your HTML:
41
41
  ## Optional CSS
42
42
 
43
43
  ```html
44
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@vipros-org/sdk@latest/vipros-sdk.min.css">
44
+ <link
45
+ rel="stylesheet"
46
+ href="https://cdn.jsdelivr.net/npm/@vipros-org/sdk@latest/vipros-sdk.min.css"
47
+ />
45
48
  ```
46
-
47
- ## API
48
-
49
- | Method | Description |
50
- |--------|-------------|
51
- | `ViprosSDK.init(config)` | Initialize with API key |
52
- | `ViprosSDK.getProductData(ean)` | Get product data |
53
- | `ViprosSDK.getStats()` | Runtime statistics |
54
- | `ViprosSDK.clearCache()` | Clear cached data |
55
- | `ViprosSDK.refreshAll()` | Refresh all cards |
56
- | `ViprosSDK.on(event, cb)` | Listen for events |
57
-
58
- ## Support
59
-
60
- - Email: tech@vipros.fr
61
- - Issues: https://github.com/Do-It-VIPros/vipros-connect/issues
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vipros-org/sdk",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "description": "VIPros Partner SDK - Cashback and loyalty points integration for e-commerce",
5
5
  "main": "vipros-sdk.min.js",
6
6
  "module": "vipros-sdk.js",
@@ -18,12 +18,8 @@
18
18
  "e-commerce",
19
19
  "vipoints"
20
20
  ],
21
- "author": "VIPros <tech@vipros.fr>",
21
+ "author": "VIPros",
22
22
  "license": "UNLICENSED",
23
- "repository": {
24
- "type": "git",
25
- "url": "https://github.com/Do-It-VIPros/vipros-connect.git"
26
- },
27
23
  "homepage": "https://vipros.fr",
28
24
  "publishConfig": {
29
25
  "access": "public",
package/vipros-sdk.css CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * VIPros SDK - CSS File
3
3
  * Version: 3.0.0-unified
4
- * Generated: 2026-02-10T11:29:54.359Z
4
+ * Generated: 2026-02-11T13:45:30.171Z
5
5
  */
6
6
 
7
7
  /* VIPros SDK Base Styles */
package/vipros-sdk.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * VIPros SDK v3.0.0-unified - Production Build
3
- * Generated: 2026-02-10T11:29:53.281Z
3
+ * Generated: 2026-02-11T13:45:27.756Z
4
4
  * Environment: Production
5
5
  */
6
6
  var ViprosSDK = (function () {
@@ -2951,7 +2951,7 @@ var ViprosSDK = (function () {
2951
2951
  return false
2952
2952
  }
2953
2953
 
2954
- // NE PAS retry les erreurs rate limit - les faire remonter immédiatement pour affichage
2954
+ // Ne pas retry les erreurs rate limit - remonter immédiatement
2955
2955
  if (error.status === 429 || error.type === 'RATE_LIMIT_ERROR') {
2956
2956
  return false
2957
2957
  }
@@ -3809,7 +3809,7 @@ var ViprosSDK = (function () {
3809
3809
  ...userConfig
3810
3810
  });
3811
3811
 
3812
- this.debugLog(`🚀 Initialisation VIPros SDK v${this.version}`);
3812
+ this.debugLog(`Initialisation VIPros SDK v${this.version}`);
3813
3813
  this.debugLog('Configuration:', this.config);
3814
3814
 
3815
3815
  // Enregistrer le composant Web Components immédiatement
@@ -3823,7 +3823,7 @@ var ViprosSDK = (function () {
3823
3823
  this.isInitialized = true;
3824
3824
  this.emitEvent('sdk-ready', { version: this.version, config: this.config });
3825
3825
 
3826
- this.debugLog('🎯 SDK initialisé avec lazy loading - services créés à la demande');
3826
+ this.debugLog('SDK initialisé avec lazy loading - services créés à la demande');
3827
3827
 
3828
3828
  return this
3829
3829
  }
@@ -3833,7 +3833,7 @@ var ViprosSDK = (function () {
3833
3833
  */
3834
3834
  get apiClient() {
3835
3835
  if (!this._apiClient) {
3836
- this.debugLog('📡 Création lazy d\'ApiClient');
3836
+ this.debugLog('Création lazy d\'ApiClient');
3837
3837
  this._apiClient = new ApiClient(this.config);
3838
3838
  }
3839
3839
  return this._apiClient
@@ -3844,7 +3844,7 @@ var ViprosSDK = (function () {
3844
3844
  */
3845
3845
  get cacheService() {
3846
3846
  if (!this._cacheService) {
3847
- this.debugLog('💾 Création lazy de CacheService');
3847
+ this.debugLog('Création lazy de CacheService');
3848
3848
  this._cacheService = new CacheService(this.config.cacheTimeout || 300000);
3849
3849
  }
3850
3850
  return this._cacheService
@@ -3855,7 +3855,7 @@ var ViprosSDK = (function () {
3855
3855
  */
3856
3856
  get syncService() {
3857
3857
  if (!this._syncService && this.config.syncEnabled) {
3858
- this.debugLog('🔄 Création lazy d\'EanSyncService');
3858
+ this.debugLog('Création lazy d\'EanSyncService');
3859
3859
  this._syncService = new EanSyncService(this.apiClient, this.cacheService, this.config);
3860
3860
 
3861
3861
  // Connecter les événements de synchronisation lors de la première création
@@ -3868,7 +3868,7 @@ var ViprosSDK = (function () {
3868
3868
  * Initialize all services immediately (for cases requiring eager loading)
3869
3869
  */
3870
3870
  initializeServicesEager() {
3871
- this.debugLog('🚀 Initialisation eager de tous les services...');
3871
+ this.debugLog('Initialisation eager de tous les services...');
3872
3872
 
3873
3873
  // Access getters to trigger lazy initialization
3874
3874
  const api = this.apiClient;
@@ -3876,7 +3876,7 @@ var ViprosSDK = (function () {
3876
3876
  const sync = this.syncService;
3877
3877
 
3878
3878
  this._servicesInitialized = true;
3879
- this.debugLog('Tous les services initialisés (eager)');
3879
+ this.debugLog('Tous les services initialisés (eager)');
3880
3880
 
3881
3881
  return { api, cache, sync }
3882
3882
  }
@@ -3945,7 +3945,7 @@ var ViprosSDK = (function () {
3945
3945
  ViprosOfferCard.setSDKInstance(this);
3946
3946
  customElements.define('vipros-offer-card', ViprosOfferCard);
3947
3947
  this.stats.componentsRegistered++;
3948
- this.debugLog('vipros-offer-card registered');
3948
+ this.debugLog('vipros-offer-card registered');
3949
3949
  }
3950
3950
  }
3951
3951
 
@@ -3954,7 +3954,7 @@ var ViprosSDK = (function () {
3954
3954
  */
3955
3955
  scanAndConvert() {
3956
3956
  const containers = document.querySelectorAll(this.config.containerSelector);
3957
- this.debugLog(`🔍 Scan: ${containers.length} containers data-ean trouvés`);
3957
+ this.debugLog(`Scan: ${containers.length} containers data-ean trouvés`);
3958
3958
 
3959
3959
  containers.forEach(container => {
3960
3960
  const ean = container.getAttribute('data-ean');
@@ -3968,7 +3968,7 @@ var ViprosSDK = (function () {
3968
3968
 
3969
3969
  // Remplacer le container
3970
3970
  container.parentNode.replaceChild(offerCard, container);
3971
- this.debugLog(`🔄 Converti data-ean="${ean}" vers Web Component`);
3971
+ this.debugLog(`Converti data-ean="${ean}" vers Web Component`);
3972
3972
  }
3973
3973
  });
3974
3974
  }
@@ -4005,7 +4005,7 @@ var ViprosSDK = (function () {
4005
4005
  const cached = this.cache.get(cacheKey);
4006
4006
  if (Date.now() - cached.timestamp < this.config.cacheTimeout) {
4007
4007
  this.stats.cacheHits++;
4008
- this.debugLog(`💾 Cache hit for EAN ${ean}`);
4008
+ this.debugLog(`Cache hit for EAN ${ean}`);
4009
4009
  return cached.data
4010
4010
  }
4011
4011
  }
@@ -4034,12 +4034,12 @@ var ViprosSDK = (function () {
4034
4034
  });
4035
4035
  }
4036
4036
 
4037
- this.debugLog(`📡 API data loaded for EAN ${ean} (optimized route)`);
4037
+ this.debugLog(`API data loaded for EAN ${ean}`);
4038
4038
  return data
4039
4039
 
4040
4040
  } catch (error) {
4041
4041
  this.stats.errors++;
4042
- this.debugLog(`❌ Erreur API pour EAN ${ean}:`, error);
4042
+ this.debugLog(`Erreur API pour EAN ${ean}:`, error);
4043
4043
  throw error
4044
4044
  }
4045
4045
  }
@@ -4055,7 +4055,7 @@ var ViprosSDK = (function () {
4055
4055
  cancelable: true
4056
4056
  });
4057
4057
  document.dispatchEvent(event);
4058
- this.debugLog(`📤 Event: ${eventName}`, detail);
4058
+ this.debugLog(`Event: ${eventName}`, detail);
4059
4059
  }
4060
4060
 
4061
4061
  /**
@@ -4092,7 +4092,7 @@ var ViprosSDK = (function () {
4092
4092
  */
4093
4093
  clearCache() {
4094
4094
  this.cache.clear();
4095
- this.debugLog('🗑️ Cache vidé');
4095
+ this.debugLog('Cache vidé');
4096
4096
  }
4097
4097
 
4098
4098
  /**
@@ -4105,7 +4105,7 @@ var ViprosSDK = (function () {
4105
4105
  comp.refresh();
4106
4106
  }
4107
4107
  });
4108
- this.debugLog(`🔄 Refresh de ${components.length} composants`);
4108
+ this.debugLog(`Refresh de ${components.length} composants`);
4109
4109
  }
4110
4110
 
4111
4111
  /**
@@ -4146,24 +4146,24 @@ var ViprosSDK = (function () {
4146
4146
 
4147
4147
  // Cleanup lazy-loaded services
4148
4148
  if (this._apiClient) {
4149
- this.debugLog('🧹 Nettoyage ApiClient');
4149
+ this.debugLog('Nettoyage ApiClient');
4150
4150
  this._apiClient = null;
4151
4151
  }
4152
4152
 
4153
4153
  if (this._cacheService) {
4154
- this.debugLog('🧹 Nettoyage CacheService');
4154
+ this.debugLog('Nettoyage CacheService');
4155
4155
  this._cacheService = null;
4156
4156
  }
4157
4157
 
4158
4158
  if (this._syncService) {
4159
- this.debugLog('🧹 Nettoyage SyncService');
4159
+ this.debugLog('Nettoyage SyncService');
4160
4160
  this._syncService = null;
4161
4161
  }
4162
4162
 
4163
4163
  this._servicesInitialized = false;
4164
4164
  this.isInitialized = false;
4165
4165
 
4166
- this.debugLog('🔥 SDK détruit avec nettoyage des services lazy');
4166
+ this.debugLog('SDK détruit');
4167
4167
  }
4168
4168
  }
4169
4169
 
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * VIPros SDK - CSS File
3
3
  * Version: 3.0.0-unified
4
- * Generated: 2026-02-10T11:29:54.359Z
4
+ * Generated: 2026-02-11T13:45:30.171Z
5
5
  */
6
6
 
7
7
  /* VIPros SDK Base Styles */
package/vipros-sdk.min.js CHANGED
@@ -1,2 +1,2 @@
1
- /*! VIPros SDK v3.0.0-unified - Production Minified - 2026-02-10T11:29:53.281Z */
2
- var ViprosSDKBundle=function(){"use strict";class e{constructor(e=!1){this.debug=e,this.templates=new Map,this.baseUrl=this.detectBaseUrl()}detectBaseUrl(){const e=window.location.origin;return window.location.hostname.includes("ddev.site"),e+"/api/sdk/components/templates"}async loadTemplate(e){if(this.templates.has(e))return this.templates.get(e);try{const t=await fetch(`${this.baseUrl}/${e}.html`);if(!t.ok)throw new Error(`Template ${e} not found: ${t.status}`);const s=await t.text();return this.templates.set(e,s),s}catch(t){return this.getFallbackTemplate(e)}}async render(e,t={}){const s=await this.loadTemplate(e);return this.interpolate(s,t)}interpolate(e,t){let s=this.processConditionalBlocks(e,t);return s=s.replace(/\{\{([^}#/][^}]*)\}\}/g,(e,s)=>{const i=this.resolveNestedKey(t,s.trim());return null!==i?i:""}),s}resolveNestedKey(e,t){return t.startsWith("#")||t.startsWith("/")?"":t.split(".").reduce((e,t)=>e&&void 0!==e[t]?e[t]:null,e)}processConditionalBlocks(e,t){let s=e,i=0;for(;(s.includes("{{#if")||s.includes("{{#unless"))&&(i++,!(i>10));){const e=s;if(s=this.processIfBlocks(s,t),s=this.processUnlessBlocks(s,t),s===e)break}return s}processIfBlocks(e,t){return e.replace(/\{\{#if\s+([^}]+)\}\}((?:(?!\{\{#if)[\s\S])*?)\{\{\/if\}\}/g,(e,s,i)=>{const r=this.resolveNestedKey(t,s.trim()),n=Boolean(r),a=i.split(/\{\{else\}\}/);return 2===a.length?n?a[0]:a[1]:n?i:""})}processUnlessBlocks(e,t){return e.replace(/\{\{#unless\s+([^}]+)\}\}((?:(?!\{\{#unless)[\s\S])*?)\{\{\/unless\}\}/g,(e,s,i)=>{const r=this.resolveNestedKey(t,s.trim());return!Boolean(r)?i:""})}handleConditional(e,t,s){const i=t.split(" ")[1],r=this.resolveNestedKey(e,i),n=Boolean(r);return(s?n:!n)?"":"\x3c!-- condition-false --\x3e"}getFallbackTemplate(e){return{CashbackTemplate:'\n <div class="vipros-offer-card cashback-mode">\n <div class="offer-content">\n <div class="main-value">\n <span class="amount">{{cashback.value}}</span>\n <span class="currency">€</span>\n <span class="label">remboursés</span>\n </div>\n </div>\n </div>\n ',VIPointsTemplate:'\n <div class="vipros-offer-card vipoints-mode">\n <div class="offer-content">\n <div class="main-value">\n <span class="amount">{{vipoints.perTenEuros}}</span>\n <span class="label">VIPoints</span>\n </div>\n </div>\n </div>\n ',LoadingTemplate:'\n <div class="vipros-offer-card loading-state">\n <div class="loading-text">Recherche...</div>\n </div>\n ',ErrorTemplate:'\n <div class="vipros-offer-card error-state">\n <div class="error-text">{{message}}</div>\n <div class="debug-notice">Erreur affichée car le mode debug est activé</div>\n </div>\n '}[e]||'<div class="vipros-offer-card">Template not found</div>'}async preloadTemplates(){const e=["CashbackTemplate","VIPointsTemplate","LoadingTemplate","ErrorTemplate"].map(e=>this.loadTemplate(e).catch(e=>(this.debug,null)));await Promise.all(e),this.debug}clearCache(){this.templates.clear()}}class t{static transform(e,t=null){if(!e)return null;const s=Boolean(e.cashback?.value>0),i=e.brand?.generosity_rate||0,r=this.calculateVIPoints(i,t);return{id:e.id||"not_found",ean:e.ean,name:e.name||"Produit inconnu",price:t,brand:this.transformBrandData(e.brand),cashback:this.transformCashbackData(e.cashback),vipoints:r,hasCashback:s,viprosLink:this.buildViprosLink(e),vipointsImageUrl:null}}static transformBrandData(e){if(!e)return{name:"Marque inconnue",displayName:null,logoUrl:null,generosityRate:0};const t=e.name&&"Marque inconnue"!==e.name?e.name:null;return{name:e.name||"Marque inconnue",displayName:t,logoUrl:e.logo_url||null,generosityRate:e.generosity_rate||0}}static transformCashbackData(e){return e?{value:e.value||0,name:e.name||null,imageUrl:e.image_url||null,startDate:e.start_date||null,endDate:e.end_date||null}:{value:0,name:null,imageUrl:null,startDate:null,endDate:null}}static calculateVIPoints(e,t){let s=0,i=!1,r=!1;return e>0&&(i=!0,t&&t>0?(s=Math.floor(e*t/10),r=!0):(s=1,r=!1)),{perTenEuros:s,generosityRate:e,hasBonus:i,showExact:r}}static determineDisplayMode(e){return e?e.hasCashback?"cashback":e.vipoints.hasBonus?"vipoints":"empty":"empty"}static validate(e){if(!e)return{isValid:!1,errors:["No data provided"]};const t=[];return e.ean||t.push("EAN is required"),e.hasCashback&&!e.cashback.value&&t.push("Cashback value is required when hasCashback is true"),e.vipoints.hasBonus&&!e.vipoints.generosityRate&&t.push("Generosity rate is required when VIPoints bonus is available"),{isValid:0===t.length,errors:t}}static prepareTemplateData(e,t=null){return e?{...e,vipointsImageUrl:t||this.getDefaultVIPointsImageUrl()}:null}static buildViprosLink(e){const t=e.vipros_link||"https://vipros.fr",s=this.getSalesPointName(e),i="undefined"!=typeof window?window.location.href:"",r=new URL(t);return s&&r.searchParams.set("origin",s),i&&r.searchParams.set("origin_url",i),r.toString()}static getSalesPointName(e){if(e.sales_points&&Array.isArray(e.sales_points)){const t=e.sales_points.find(e=>e.name);if(t)return t.name}if("undefined"!=typeof window){return window.location.hostname.replace(/^www\./,"").replace(/\./g," ").split(" ")[0]}return null}static getDefaultVIPointsImageUrl(){return"/api/sdk/assets/image-vipoints.jpg"}}class s{static resolveDisplayMode(e){return e?e.hasCashback?"cashback":e.vipoints.hasBonus?"vipoints":"empty":"empty"}static resolveTemplateName(e){return{cashback:"CashbackTemplate",vipoints:"VIPointsTemplate",loading:"LoadingTemplate",error:"ErrorTemplate",empty:null,hidden:null}[e]||null}static shouldDisplay(e){return!["empty","hidden"].includes(e)}static resolveContainerClass(e){return`vipros-offer-card ${{cashback:"cashback-mode",vipoints:"vipoints-mode",loading:"loading-state",error:"error-state",empty:"empty-state",hidden:"hidden-state"}[e]||""}`}static validateDisplayMode(e){return["cashback","vipoints","loading","error","empty","hidden"].includes(e)?e:"error"}static analyze(e,t={}){const{isLoading:s=!1,error:i=null,debug:r=!1}=t;if(i)return r?{mode:"error",template:"ErrorTemplate",shouldDisplay:!0,containerClass:this.resolveContainerClass("error"),data:{message:i.message||"Une erreur est survenue",debugMode:!0}}:{mode:"hidden",template:null,shouldDisplay:!1,containerClass:this.resolveContainerClass("hidden"),data:{}};if(s)return{mode:"loading",template:"LoadingTemplate",shouldDisplay:!0,containerClass:this.resolveContainerClass("loading"),data:{}};const n=this.resolveDisplayMode(e),a=this.resolveTemplateName(n),o=this.shouldDisplay(n),c=this.resolveContainerClass(n);return{mode:this.validateDisplayMode(n),template:a,shouldDisplay:o,containerClass:c,data:o?e:{}}}static hasMinimumRequiredData(e){return!!e&&(!!e.ean&&(e.hasCashback||e.vipoints.hasBonus))}static suggestDataImprovements(e){if(!e)return["Product data is required"];const t=[];return e.name&&"Produit inconnu"!==e.name||t.push("Product name could be improved"),e.hasCashback&&!e.cashback.imageUrl&&t.push("Cashback image would improve visual appeal"),!e.price&&e.vipoints.hasBonus&&t.push("Price would enable exact VIPoints calculation"),e.brand.displayName||t.push("Brand name would improve VIPoints messaging"),t}}class i{constructor(e){this.element=e,this.listeners=new Map}emit(e,t={}){const s=new CustomEvent(e,{detail:t,bubbles:!0,cancelable:!0});this.element.dispatchEvent(s),this.element.getAttribute("debug")}emitOfferLoaded(e,t){this.emit("vipros-offer-loaded",{product:e,ean:t,timestamp:Date.now()})}emitError(e,t){this.emit("vipros-offer-error",{error:{message:e.message||"Unknown error",type:e.constructor.name,stack:e.stack},ean:t,timestamp:Date.now()})}emitOfferClick(e,t,s){this.emit("vipros-offer-click",{url:e,product:t,ean:s,timestamp:Date.now()})}emitSyncStarted(e,t){this.emit("vipros-sync-started",{ean:e,url:t,timestamp:Date.now()})}emitSyncSuccess(e,t){this.emit("vipros-sync-success",{ean:e,result:t,timestamp:Date.now()})}emitSyncError(e,t){this.emit("vipros-sync-error",{ean:e,error:{message:t.message||"Sync error",type:t.constructor.name},timestamp:Date.now()})}attachLinkListeners(e,t,s){e.querySelectorAll("a[href]").forEach(e=>{const i=i=>{this.emitOfferClick(e.href,t,s),window.gtag&&window.gtag("event","vipros_offer_click",{ean:s,url:e.href,product_name:t?.name})};e.addEventListener("click",i),this.listeners.has("linkClicks")||this.listeners.set("linkClicks",[]),this.listeners.get("linkClicks").push({link:e,handler:i})})}cleanup(){this.listeners.has("linkClicks")&&this.listeners.get("linkClicks").forEach(({link:e,handler:t})=>{e.removeEventListener("click",t)}),this.listeners.clear()}enableGlobalDebugging(){["vipros-offer-loaded","vipros-offer-error","vipros-offer-click","vipros-sync-started","vipros-sync-success","vipros-sync-error"].forEach(e=>{document.addEventListener(e,e=>{})})}static emit(e,t,s={}){new i(e).emit(t,s)}static emitOfferLoaded(e,t,s){new i(e).emitOfferLoaded(t,s)}static emitError(e,t,s){new i(e).emitError(t,s)}}class r extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this.templateLoader=new e,this.eventManager=new i(this),this.state={isLoading:!1,productData:null,error:null,apiClient:null},this.init=this.init.bind(this),this.loadProduct=this.loadProduct.bind(this),this.render=this.render.bind(this)}static get observedAttributes(){return["ean","price","api-base-url","api-key","primary-color","text-color","background-color","card-bonus-bg","card-bonus-color"]}get ean(){return this.getAttribute("ean")||this.getConfigValue("ean")}get price(){const e=parseFloat(this.getAttribute("price"))||0;if(e>0)return e;const t=this.getConfigValue("price");return t&&parseFloat(t)>0?parseFloat(t):null}get apiBaseUrl(){return this.getConfigValue("apiBaseUrl")||this.getAttribute("api-base-url")||this.detectFallbackApiBaseUrl()}get apiKey(){return this.getConfigValue("apiKey")||this.getAttribute("api-key")}get primaryColor(){return this.getAttribute("primary-color")||this.getConfigValue("primaryColor")}get textColor(){return this.getAttribute("text-color")||this.getConfigValue("textColor")}get backgroundColor(){return this.getAttribute("background-color")||this.getConfigValue("backgroundColor")}get cardBonusBg(){return this.getAttribute("card-bonus-bg")||this.getConfigValue("cardBonusBg")}get cardBonusColor(){return this.getAttribute("card-bonus-color")||this.getConfigValue("cardBonusColor")}getConfigValue(e){const t=this.getSDKInstance();return t?.config?.[e]||null}getSDKInstance(){return"undefined"!=typeof window?window.ViprosSDK:null}detectFallbackApiBaseUrl(){if("undefined"==typeof window)return this.log("[ViprosOfferCard] No window object - defaulting to production API"),"https://msys.vipros.fr/api";try{if(!window.location||"string"!=typeof window.location.hostname)return this.log("[ViprosOfferCard] Invalid window.location - defaulting to production API"),"https://msys.vipros.fr/api";const e=window.location.protocol||"https:",t=window.location.hostname.toLowerCase();return t&&0!==t.length?"file:"===e||"localhost"===t||t.startsWith("127.0.0.1")||t.startsWith("0.0.0.0")?(this.log("[ViprosOfferCard] Local development detected - using DDEV fallback"),"https://vipros-connect.ddev.site/api"):"vipros-connect.ddev.site"===t?`${e}//${t}/api`:"msys.preprod.vipros.fr"===t?`${e}//msys.preprod.vipros.fr/api`:t.endsWith(".vipros.fr")?(this.log(`[ViprosOfferCard] VIPros subdomain detected: ${t}`),`${e}//${t}/api`):(this.log(`[ViprosOfferCard] Unknown domain: ${t} - defaulting to production API`),"https://msys.vipros.fr/api"):(this.log("[ViprosOfferCard] Empty hostname - defaulting to production API"),"https://msys.vipros.fr/api")}catch(e){return this.log(`[ViprosOfferCard] Error detecting API base URL: ${e.message} - defaulting to production`),"https://msys.vipros.fr/api"}}connectedCallback(){this.log("[ViprosOfferCard] Component connected"),this.init()}attributeChangedCallback(e,t,s){t!==s&&this.isConnected&&("ean"===e?(this.log(`[ViprosOfferCard] EAN changed: ${t} → ${s}`),this.loadProduct()):["primary-color","text-color","background-color","gift-icon-color","gift-card-bonus-bg","gift-card-bonus-color","vipoints-bonus-bg","vipoints-bonus-color"].includes(e)&&(this.log(`[ViprosOfferCard] Color changed: ${e} = ${s}`),this.updateCustomColors()))}disconnectedCallback(){this.log("[ViprosOfferCard] Component disconnected"),this.cleanup()}async init(){try{this.loadGoogleFonts(),await this.loadStyles(),this.updateCustomColors(),await this.initApiClient(),await this.templateLoader.preloadTemplates(),this.ean?await this.loadProduct():this.setError(new Error("EAN requis pour afficher une offre VIPros"))}catch(e){this.logError("[ViprosOfferCard] Init error:",e),this.setError(e)}}loadGoogleFonts(){["https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;500;600;700&display=swap","https://fonts.googleapis.com/css2?family=Encode+Sans+Condensed:wght@100;200;300;400;500;600;700;800;900&display=swap"].forEach(e=>{if(!document.querySelector(`link[href="${e}"]`)){const t=document.createElement("link");t.rel="stylesheet",t.href=e,t.crossOrigin="anonymous",document.head.appendChild(t)}})}async loadStyles(){try{const e=this.templateLoader.baseUrl.replace("/components/templates","/components/styles/offer-card.css"),t=await fetch(e);if(t.ok){const e=await t.text(),s=document.createElement("style");s.textContent=e,this.shadowRoot.appendChild(s)}else this.injectFallbackStyles()}catch(e){this.logError("[ViprosOfferCard] CSS loading failed, using fallback"),this.injectFallbackStyles()}}updateCustomColors(){if(!this.shadowRoot)return;const e=this.shadowRoot.host,t={};this.primaryColor&&(t["--vipros-primary"]=this.primaryColor,t["--vipros-text-accent"]=this.primaryColor),this.textColor&&(t["--vipros-text-main"]=this.textColor),this.backgroundColor&&(t["--vipros-background"]=this.backgroundColor),this.cardBonusBg&&(t["--card-bonus-bg"]=this.cardBonusBg),this.cardBonusColor&&(t["--card-bonus-color"]=this.cardBonusColor),Object.entries(t).forEach(([t,s])=>{e.style.setProperty(t,s)}),this.log("[ViprosOfferCard] Custom colors applied:",t)}injectFallbackStyles(){const e=document.createElement("style");e.textContent="\n .vipros-offer-card { \n display: block; \n padding: 20px; \n background: #e8ecf8; \n border-radius: 12px; \n font-family: sans-serif; \n }\n .loading-content, .error-content { \n text-align: center; \n padding: 40px; \n }\n ",this.shadowRoot.appendChild(e)}log(e,...t){const s=this.getSDKInstance();s&&s.config&&s.config.debug}logError(e,...t){const s=this.getSDKInstance();s&&s.config&&s.config.debug}async initApiClient(){const e=this.getSDKInstance();if(e&&e.getApiClient)this.state.apiClient=e.getApiClient(),this.log("[ViprosOfferCard] Using shared SDK ApiClient");else{const{default:e}=await Promise.resolve().then(function(){return N});this.state.apiClient=new e({apiBaseUrl:this.apiBaseUrl,apiKey:this.apiKey}),this.log("[ViprosOfferCard] Created local ApiClient")}}async loadProduct(){if(this.ean&&!this.state.isLoading)if(this.state.apiClient){this.setLoading(!0);try{this.log(`[ViprosOfferCard] Loading product: ${this.ean}`);const e=this.getSDKInstance(),s={timeout:5e3};e?.config?.inlineSyncEnabled&&(s.enableInlineSync=!0,s.productUrl=window.location.href,this.log(`[ViprosOfferCard] Inline sync enabled for EAN ${this.ean}`));const i=await this.state.apiClient.get("/catalog/items",{ean:this.ean,items_per_page:1},s),r=i?.metadata?.bloomFilter,n=Boolean(this.getConfigValue("debug")||"true"===this.getAttribute("debug"));if(r?.skipped){if(this.log(`[ViprosOfferCard] Bloom filter skipped API call for EAN ${this.ean}`),n){const e=new Error("404 | Produit introuvable (Bloom filter)");e.status=404,e.type="BLOOM_FILTER_NOT_FOUND",e.data={ean:this.ean,reason:r.reason||"NOT_IN_FILTER"},this.setError(e)}else this.setProductData(null);return}const a=i?.sdk_metadata?.sync;if(a&&this.getConfigValue("debug")&&this.log("[ViprosOfferCard] Sync metadata:",a),i.items&&i.items.length>0){const e=t.transform(i.items[0],this.price);e.vipointsImageUrl=this.getVIPointsImageUrl(),this.setProductData(e),this.log(`[ViprosOfferCard] Product loaded: ${e.name}`);null!=a?this.log(`[ViprosOfferCard] Skipping background sync (inline sync was attempted, status: ${a.reason||"unknown"})`):this.triggerBackgroundSync(),this.eventManager.emitOfferLoaded(e,this.ean)}else this.log(`[ViprosOfferCard] No product found for EAN: ${this.ean}`),this.setProductData(null)}catch(e){if(this.logError(`[ViprosOfferCard] Error loading EAN ${this.ean}:`,e),429===e.status||"RATE_LIMIT_ERROR"===e.type){const e=new Error("API rate limit exceeded - Trop de requêtes simultanées");e.status=429,e.type="RATE_LIMIT_ERROR",this.setError(e)}else this.setError(e)}finally{this.setLoading(!1)}}else setTimeout(()=>this.loadProduct(),100)}setLoading(e){this.state.isLoading=e,this.render()}setProductData(e){this.state.productData=e,this.state.error=null}setError(e){this.state.error=e,this.state.productData=null,this.render(),this.eventManager.emitError(e,this.ean)}async render(){const e=s.analyze(this.state.productData,{isLoading:this.state.isLoading,error:this.state.error,debug:this.getConfigValue("debug")||!1});if(e.shouldDisplay){if(e.template){const t=await this.templateLoader.render(e.template,e.data);this.updateShadowContent(t),this.state.isLoading||this.attachEventListeners()}}else this.updateShadowContent('<div class="vipros-offer-card hidden"></div>')}async renderLoading(){await this.render()}updateShadowContent(e){const t=Array.from(this.shadowRoot.querySelectorAll("style")).map(e=>e.textContent);this.shadowRoot.replaceChildren();const s=document.createElement("div");for(s.innerHTML=e;s.firstChild;)this.shadowRoot.appendChild(s.firstChild);t.forEach(e=>{const t=document.createElement("style");t.textContent=e,this.shadowRoot.appendChild(t)})}attachEventListeners(){this.state.productData&&this.eventManager.attachLinkListeners(this.shadowRoot,this.state.productData,this.ean)}getVIPointsImageUrl(){return`${(this.apiBaseUrl||"").replace("/api","")}/api/sdk/assets/image-vipoints.jpg`}triggerBackgroundSync(){const e=this.getSDKInstance();e?.syncService&&setTimeout(()=>{this.log(`[ViprosOfferCard] Background sync for EAN ${this.ean}`),e.syncProductInBackground(this.ean,window.location.href)},100)}cleanup(){this.eventManager.cleanup(),this.state.apiClient=null,this.state.productData=null}}r.setSDKInstance=function(e){};class n{static create(e={}){const t=n.getDefaultConfig(),s=n.mergeConfig(t,e);return n.validateConfig(s)}static getDefaultConfig(){return{apiBaseUrl:n.detectApiBaseUrl(),apiKey:null,timeout:1e4,ean:null,price:null,primaryColor:null,textColor:null,backgroundColor:null,cardBonusBg:null,cardBonusColor:null,cacheTimeout:3e5,cachePrefix:"vipros_sdk_",maxCacheSize:100,containerSelector:"[data-ean]",eanAttribute:"data-ean",renderPosition:"replace",excludeSelectors:[".vipros-offer","[data-vipros-exclude]"],templates:{},styling:{theme:"minimal",customCSS:{},inlineStyles:!0,cssPrefix:"vipros-",responsive:!0},batchRequests:!0,lazyLoad:!0,maxConcurrentRequests:3,debounceDelay:300,hideOnError:!1,retryOnError:!0,gracefulDegradetion:!0,syncEnabled:!0,syncOptions:{cooldownTime:864e5,syncDelay:100,maxRetries:3,retryDelay:1e3},debug:!1,verbose:!1,logLevel:"warn",onReady:null,onOfferFound:null,onOfferRendered:null,onOfferLoaded:null,onError:null,features:{analyticsTracking:!1,performanceMonitoring:!1,a11yEnhancements:!0,seoOptimizations:!0},locale:"fr-FR",currency:"EUR",dateFormat:"DD/MM/YYYY",version:"1.0.0"}}static mergeConfig(e,t){return n.deepMerge(e,t)}static deepMerge(e,t){const s={...e};for(const[e,i]of Object.entries(t))null!=i&&(n.isObject(i)&&n.isObject(s[e])?s[e]=n.deepMerge(s[e],i):s[e]=i);return s}static isObject(e){return e&&"object"==typeof e&&!Array.isArray(e)}static validateConfig(e){const t=[];if(e.apiBaseUrl&&"string"==typeof e.apiBaseUrl)try{new URL(e.apiBaseUrl)}catch(e){t.push("apiBaseUrl must be a valid URL")}else t.push("apiBaseUrl must be a valid string");if(e.apiKey||t.push("apiKey is required"),e.apiKey&&"string"!=typeof e.apiKey&&t.push("apiKey must be a string"),e.timeout&&("number"!=typeof e.timeout||e.timeout<=0)&&t.push("timeout must be a positive number"),e.cacheTimeout&&("number"!=typeof e.cacheTimeout||e.cacheTimeout<0)&&t.push("cacheTimeout must be a non-negative number"),e.maxCacheSize&&("number"!=typeof e.maxCacheSize||e.maxCacheSize<=0)&&t.push("maxCacheSize must be a positive number"),e.containerSelector&&"string"!=typeof e.containerSelector&&t.push("containerSelector must be a string"),e.eanAttribute&&"string"!=typeof e.eanAttribute&&t.push("eanAttribute must be a string"),e.styling){const s=["minimal","branded","custom"];e.styling.theme&&!s.includes(e.styling.theme)&&t.push(`styling.theme must be one of: ${s.join(", ")}`),e.styling.customCSS&&!n.isObject(e.styling.customCSS)&&t.push("styling.customCSS must be an object")}e.maxConcurrentRequests&&("number"!=typeof e.maxConcurrentRequests||e.maxConcurrentRequests<=0)&&t.push("maxConcurrentRequests must be a positive number"),e.debounceDelay&&("number"!=typeof e.debounceDelay||e.debounceDelay<0)&&t.push("debounceDelay must be a non-negative number");const s=["error","warn","info","debug"];e.logLevel&&!s.includes(e.logLevel)&&t.push(`logLevel must be one of: ${s.join(", ")}`);const i=["onReady","onOfferFound","onOfferRendered","onOfferLoaded","onError"];for(const s of i)e[s]&&"function"!=typeof e[s]&&t.push(`${s} must be a function`);if(e.locale&&"string"!=typeof e.locale&&t.push("locale must be a string"),e.currency&&"string"!=typeof e.currency&&t.push("currency must be a string"),t.length>0){const e=new Error(`Configuration validation failed:\n${t.join("\n")}`);throw e.validationErrors=t,e}return n.processConfig(e)}static processConfig(e){const t={...e};if(t.apiBaseUrl=t.apiBaseUrl.replace(/\/$/,""),t.containerSelector.startsWith("[")||t.containerSelector.startsWith(".")||t.containerSelector.startsWith("#")||(t.containerSelector=`[${t.eanAttribute}]`),"debug"===t.logLevel?(t.debug=!0,t.verbose=!0):"info"===t.logLevel&&(t.debug=!0),t.styling.customCSS){const e={};for(const[s,i]of Object.entries(t.styling.customCSS)){e[s.startsWith("--")?s:`--vipros-${s}`]=i}t.styling.customCSS=e}return t.cachePrefix=`${t.cachePrefix}v${t.version.replace(/\./g,"_")}_`,t.derived={isProduction:!t.debug,shouldCache:t.cacheTimeout>0,shouldBatch:t.batchRequests&&t.maxConcurrentRequests>1,shouldLazyLoad:t.lazyLoad,hasCustomStyling:"custom"===t.styling.theme||Object.keys(t.styling.customCSS||{}).length>0},t}static createSecureConfig(e,t={}){const s={apiBaseUrl:t.apiBaseUrl,allowedFeatures:t.allowedFeatures,rateLimits:t.rateLimits,version:t.version};return n.create({...s,...e})}static validateRuntimeConfig(e){if(!e)throw new Error("Configuration is required");if(!e.derived)throw new Error("Configuration has not been processed");return!0}static getConfigSummary(e){return{version:e.version,apiBaseUrl:e.apiBaseUrl,theme:e.styling.theme,cacheEnabled:e.derived.shouldCache,debugMode:e.debug,features:Object.keys(e.features).filter(t=>e.features[t])}}static detectApiBaseUrl(e=!1){try{if("undefined"==typeof window)return"https://msys.vipros.fr/api";if(!window.location||"string"!=typeof window.location.hostname)return"https://msys.vipros.fr/api";const e=window.location.protocol||"https:",t=window.location.hostname.toLowerCase();return t&&0!==t.length?"file:"===e||"localhost"===t||t.startsWith("127.0.0.1")||t.startsWith("0.0.0.0")||t.includes(":")&&(t.includes("localhost")||t.includes("127.0.0.1"))?"https://vipros-connect.ddev.site/api":"vipros-connect.ddev.site"===t?`${e}//${t}/api`:"msys.preprod.vipros.fr"===t?`${e}//msys.preprod.vipros.fr/api`:t.endsWith(".vipros.fr")?`${e}//${t}/api`:(/^\d+\.\d+\.\d+\.\d+$/.test(t),"https://msys.vipros.fr/api"):"https://msys.vipros.fr/api"}catch(e){return"https://msys.vipros.fr/api"}}}class a{constructor(){this.events=new Map,this.maxListeners=10}on(e,t){if("function"!=typeof t)throw new TypeError("Callback must be a function");this.events.has(e)||this.events.set(e,[]);const s=this.events.get(e);return s.length,this.maxListeners,s.push(t),this}once(e,t){if("function"!=typeof t)throw new TypeError("Callback must be a function");const s=(...i)=>{this.off(e,s),t.apply(this,i)};return this.on(e,s)}off(e,t){if(!this.events.has(e))return this;if(!t)return this.events.delete(e),this;const s=this.events.get(e),i=s.indexOf(t);return-1!==i&&s.splice(i,1),0===s.length&&this.events.delete(e),this}emit(e,...t){if(!this.events.has(e))return!1;const s=this.events.get(e).slice();for(const e of s)try{e.apply(this,t)}catch(e){this.emit("error",e)}return!0}removeAllListeners(e=null){return e?this.events.delete(e):this.events.clear(),this}listenerCount(e){return this.events.has(e)?this.events.get(e).length:0}getMaxListeners(){return this.maxListeners}setMaxListeners(e){if("number"!=typeof e||e<0)throw new TypeError("Max listeners must be a non-negative number");return this.maxListeners=e,this}eventNames(){return Array.from(this.events.keys())}listeners(e){return this.events.has(e)?this.events.get(e).slice():[]}}var o=Uint8Array,c=Uint16Array,l=Int32Array,h=new o([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),u=new o([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),d=new o([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),p=function(e,t){for(var s=new c(31),i=0;i<31;++i)s[i]=t+=1<<e[i-1];var r=new l(s[30]);for(i=1;i<30;++i)for(var n=s[i];n<s[i+1];++n)r[n]=n-s[i]<<5|i;return{b:s,r:r}},m=p(h,2),g=m.b,f=m.r;g[28]=258,f[258]=28;for(var y=p(u,0).b,b=new c(32768),v=0;v<32768;++v){var C=(43690&v)>>1|(21845&v)<<1;C=(61680&(C=(52428&C)>>2|(13107&C)<<2))>>4|(3855&C)<<4,b[v]=((65280&C)>>8|(255&C)<<8)>>1}var w=function(e,t,s){for(var i=e.length,r=0,n=new c(t);r<i;++r)e[r]&&++n[e[r]-1];var a,o=new c(t);for(r=1;r<t;++r)o[r]=o[r-1]+n[r-1]<<1;if(s){a=new c(1<<t);var l=15-t;for(r=0;r<i;++r)if(e[r])for(var h=r<<4|e[r],u=t-e[r],d=o[e[r]-1]++<<u,p=d|(1<<u)-1;d<=p;++d)a[b[d]>>l]=h}else for(a=new c(i),r=0;r<i;++r)e[r]&&(a[r]=b[o[e[r]-1]++]>>15-e[r]);return a},S=new o(288);for(v=0;v<144;++v)S[v]=8;for(v=144;v<256;++v)S[v]=9;for(v=256;v<280;++v)S[v]=7;for(v=280;v<288;++v)S[v]=8;var E=new o(32);for(v=0;v<32;++v)E[v]=5;var k=w(S,9,1),L=w(E,5,1),R=function(e){for(var t=e[0],s=1;s<e.length;++s)e[s]>t&&(t=e[s]);return t},A=function(e,t,s){var i=t/8|0;return(e[i]|e[i+1]<<8)>>(7&t)&s},I=function(e,t){var s=t/8|0;return(e[s]|e[s+1]<<8|e[s+2]<<16)>>(7&t)},D=function(e){return(e+7)/8|0},T=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],_=function(e,t,s){var i=new Error(t||T[e]);if(i.code=e,Error.captureStackTrace&&Error.captureStackTrace(i,_),!s)throw i;return i},B=function(e,t,s,i){var r=e.length;if(!r||t.f&&!t.l)return s||new o(0);var n=!s,a=n||2!=t.i,c=t.i;n&&(s=new o(3*r));var l=function(e){var t=s.length;if(e>t){var i=new o(Math.max(2*t,e));i.set(s),s=i}},p=t.f||0,m=t.p||0,f=t.b||0,b=t.l,v=t.d,C=t.m,S=t.n,E=8*r;do{if(!b){p=A(e,m,1);var T=A(e,m+1,3);if(m+=3,!T){var B=e[(M=D(m)+4)-4]|e[M-3]<<8,U=M+B;if(U>r){c&&_(0);break}a&&l(f+B),s.set(e.subarray(M,U),f),t.b=f+=B,t.p=m=8*U,t.f=p;continue}if(1==T)b=k,v=L,C=9,S=5;else if(2==T){var O=A(e,m,31)+257,V=A(e,m+10,15)+4,P=O+A(e,m+5,31)+1;m+=14;for(var $=new o(P),x=new o(19),N=0;N<V;++N)x[d[N]]=A(e,m+3*N,7);m+=3*V;var z=R(x),K=(1<<z)-1,F=w(x,z,1);for(N=0;N<P;){var M,q=F[A(e,m,K)];if(m+=15&q,(M=q>>4)<16)$[N++]=M;else{var j=0,W=0;for(16==M?(W=3+A(e,m,3),m+=2,j=$[N-1]):17==M?(W=3+A(e,m,7),m+=3):18==M&&(W=11+A(e,m,127),m+=7);W--;)$[N++]=j}}var Q=$.subarray(0,O),H=$.subarray(O);C=R(Q),S=R(H),b=w(Q,C,1),v=w(H,S,1)}else _(1);if(m>E){c&&_(0);break}}a&&l(f+131072);for(var G=(1<<C)-1,X=(1<<S)-1,J=m;;J=m){var Y=(j=b[I(e,m)&G])>>4;if((m+=15&j)>E){c&&_(0);break}if(j||_(2),Y<256)s[f++]=Y;else{if(256==Y){J=m,b=null;break}var Z=Y-254;if(Y>264){var ee=h[N=Y-257];Z=A(e,m,(1<<ee)-1)+g[N],m+=ee}var te=v[I(e,m)&X],se=te>>4;te||_(3),m+=15&te;H=y[se];if(se>3){ee=u[se];H+=I(e,m)&(1<<ee)-1,m+=ee}if(m>E){c&&_(0);break}a&&l(f+131072);var ie=f+Z;if(f<H){var re=0-H,ne=Math.min(H,ie);for(re+f<0&&_(3);f<ne;++f)s[f]=i[re+f]}for(;f<ie;++f)s[f]=s[f-H]}}t.l=b,t.p=J,t.b=f,t.f=p,b&&(p=1,t.m=C,t.d=v,t.n=S)}while(!p);return f!=s.length&&n?function(e,t,s){return(null==s||s>e.length)&&(s=e.length),new o(e.subarray(t,s))}(s,0,f):s.subarray(0,f)},U=new o(0);function O(e,t){var s,i,r=function(e){31==e[0]&&139==e[1]&&8==e[2]||_(6,"invalid gzip data");var t=e[3],s=10;4&t&&(s+=2+(e[10]|e[11]<<8));for(var i=(t>>3&1)+(t>>4&1);i>0;i-=!e[s++]);return s+(2&t)}(e);return r+8>e.length&&_(6,"invalid gzip data"),B(e.subarray(r,-8),{i:2},new o((i=(s=e).length,(s[i-4]|s[i-3]<<8|s[i-2]<<16|s[i-1]<<24)>>>0)),t)}function V(e,t){return B(e.subarray(((8!=(15&(s=e)[0])||s[0]>>4>7||(s[0]<<8|s[1])%31)&&_(6,"invalid zlib data"),1==(s[1]>>5&1)&&_(6,"invalid zlib data: "+(32&s[1]?"need":"unexpected")+" dictionary"),2+(s[1]>>3&4)),-4),{i:2},t,t);var s}var P="undefined"!=typeof TextDecoder&&new TextDecoder;try{P.decode(U,{stream:!0})}catch(e){}class ${constructor(e,t={}){this.debugEnabled=Boolean(t.debug);try{this.bits=this.decompress(e),this.size=8*this.bits.length,this.k=7}catch(t){this.bits=e,this.size=8*this.bits.length,this.k=7}}test(e){if(!this.isValidEan(e))return this.debug("[BloomFilter] Invalid EAN format:",e),!1;this.debug("[BloomFilter] Testing EAN:",e,"Size:",this.size,"Bits length:",this.bits.length);for(let t=0;t<this.k;t++){const s=this.hash(e+t),i=s%this.size,r=Math.floor(i/8),n=i%8,a=!!(this.bits[r]&1<<n);if(this.debug(`[BloomFilter] Hash ${t}: ${s} % ${this.size} = ${i}, byte=${r}, bit=${n}, value=${a}`),!a)return this.debug(`[BloomFilter] EAN ${e} NOT found (hash ${t} failed)`),!1}return this.debug(`[BloomFilter] EAN ${e} FOUND (all ${this.k} hashes passed)`),!0}hash(e){const t=this.getCrc32Table();let s=4294967295;for(let i=0;i<e.length;i++){s=s>>>8^t[255&(s^e.charCodeAt(i))]}return Math.abs((4294967295^s)>>>0)}getCrc32Table(){return this.crc32Table||(this.crc32Table=new Uint32Array([0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117])),this.crc32Table}isValidEan(e){return"string"==typeof e&&/^\d{8}$|^\d{12}$|^\d{13}$/.test(e)}decompress(e){try{let t=e instanceof Uint8Array?e:new Uint8Array(e);if(0===t.length)return t;if(120===t[0]){this.debug("[BloomFilter] Detected zlib/gzcompress data, inflating");try{return V(t)}catch(e){this.debug("[BloomFilter] unzlibSync failed, fallback to raw:",e.message)}}if(31===t[0]&&139===t[1]){this.debug("[BloomFilter] Detected gzip data, inflating");try{return O(t)}catch(e){this.debug("[BloomFilter] gunzipSync failed, fallback to raw:",e.message)}}}catch(e){this.debug("[BloomFilter] Decompression failed:",e.message)}const t=e instanceof Uint8Array?e:new Uint8Array(e);return this.debug("[BloomFilter] Using raw data, size:",t.length),t}getStats(){return{size:this.size,bytes:this.bits.length,hashFunctions:this.k,loaded:!0}}debug(...e){this.debugEnabled}}class x extends a{constructor(e){super(),this.config=e,this.baseUrl=this.config.apiBaseUrl,this.defaultHeaders=this.buildDefaultHeaders(),this.retryConfig={maxRetries:3,baseDelay:1e3,maxDelay:1e4},this.requestQueue=[],this.isProcessingQueue=!1,this.rateLimitInfo={remaining:null,resetTime:null,limit:null},this.bloomFilter=null,this.bloomLoaded=!1,this.bloomLoadPromise=null}buildDefaultHeaders(){const e=this.config.version||"3.0.0-unified",t={"Content-Type":"application/json",Accept:"application/json","User-Agent":`ViprosSDK/${e} (JavaScript)`,"X-SDK-Version":e,"X-SDK-Client":"JavaScript"};return this.config.apiKey&&(t["x-api-key"]=this.config.apiKey),"undefined"!=typeof window&&window.location&&(t.Referer=window.location.href,t.Origin=window.location.origin),t}async getCatalogItems(e={},t={}){this.debug("[ViprosSDK] getCatalogItems() called with filters:",e,"options:",t);const s=new URLSearchParams;Object.entries(e).forEach(([e,t])=>{null!=t&&""!==t&&s.append(e,t.toString())}),t.enableInlineSync&&(s.append("sync","auto"),t.productUrl&&s.append("product_url",t.productUrl),t.forceSync&&s.append("force_sync","1"),s.append("debug","true"));const i=`${this.baseUrl}/sdk/catalog/items${s.toString()?"?"+s.toString():""}`,r={};return t.enableInlineSync&&t.productUrl&&(r["X-Product-Url"]=t.productUrl),this.request("GET",i,null,{headers:r})}async getCatalogItemByEan(e,t={}){this.debug("[ViprosSDK] getCatalogItemByEan() called with ean:",e,"options:",t);if(await this.shouldSkipEan(e))return this.debug("[ViprosSDK] getCatalogItemByEan() - EAN not in bloom filter, skipping API call"),null;const s=new URLSearchParams;t.enableInlineSync&&(s.append("sync","auto"),t.productUrl&&s.append("product_url",t.productUrl),t.forceSync&&s.append("force_sync","1"),s.append("debug","true"));const i=s.toString(),r=`${this.baseUrl}/sdk/catalog/items/${encodeURIComponent(e)}${i?"?"+i:""}`,n={};t.enableInlineSync&&t.productUrl&&(n["X-Product-Url"]=t.productUrl);try{const t=await this.request("GET",r,null,{headers:n});return 404!==t.code&&t.item?(this.debug("[ViprosSDK] getCatalogItemByEan() - Product found:",t.item?.name),t.item):(this.debug("[ViprosSDK] getCatalogItemByEan() - Product not found for EAN:",e),null)}catch(e){return this.debug("[ViprosSDK] getCatalogItemByEan() - Error:",e?.message||e),null}}async updateProductUrls(e){if(!Array.isArray(e)||0===e.length)throw new Error("Updates must be a non-empty array");const t=`${this.baseUrl}/catalog/stores/update_urls`;return this.request("POST",t,{updates:e})}async getProductUpdates(){const e=`${this.baseUrl}/catalog/stores/get_updates`;return this.request("GET",e)}async healthCheck(){const e=`${this.baseUrl}/sdk/health`;return this.request("GET",e)}async syncProduct(e,t,s=!1){if(!e||!t)throw new Error("EAN and product URL are required for synchronization");const i=`${this.config.apiBaseUrl}/partners-stores/sync`,r={ean:e.toString(),url:t};return s&&(r.force_sync=!0),this.request("POST",i,r,{headers:{}})}async get(e,t={},s={}){if("/catalog/items"===e){if(t.ean&&!t.ean.includes(",")){this.debug("[ViprosSDK] get() method - using optimized single EAN route");const e=await this.getCatalogItemByEan(t.ean,s);return e?{items:[e],code:200}:{items:[],code:404,metadata:{ean:t.ean,optimizedRoute:!0}}}if(t.ean){const e=await this.shouldSkipEan(t.ean);if(this.debug(`[ViprosSDK] get() method - shouldSkip: ${e}`),e)return this.debug("[ViprosSDK] get() method - returning empty items, API call skipped (bloom filter)"),{items:[],metadata:{bloomFilter:{skipped:!0,reason:"NOT_IN_FILTER",ean:t.ean}}}}return this.debug("[ViprosSDK] get() method - calling getCatalogItems() with options:",s),this.getCatalogItems(t,s)}const i=`${this.baseUrl}${e}`,r=new URLSearchParams;Object.entries(t).forEach(([e,t])=>{null!=t&&""!==t&&r.append(e,t.toString())});const n=r.toString()?`${i}?${r.toString()}`:i;return this.request("GET",n)}async request(e,t,s=null,i={}){return new Promise((r,n)=>{const a={method:e,url:t,data:s,options:{retry:!0,...i},resolve:r,reject:n,attempts:0};this.requestQueue.push(a),this.processQueue()})}async processQueue(){if(!this.isProcessingQueue&&0!==this.requestQueue.length){for(this.isProcessingQueue=!0;this.requestQueue.length>0;){const e=this.requestQueue.shift();try{const t=await this.executeRequest(e);e.resolve(t)}catch(t){e.options.retry&&this.shouldRetry(t,e)?await this.scheduleRetry(e):e.reject(t)}if(null!==this.rateLimitInfo.remaining&&this.rateLimitInfo.remaining<=1){const e=this.calculateRateLimitDelay();e>0&&await this.sleep(e)}}this.isProcessingQueue=!1}}async executeRequest(e){const{method:t,url:s,data:i,options:r}=e;e.attempts++;const n={method:t,headers:{...this.defaultHeaders,...r.headers},credentials:"omit"};if(!i||"POST"!==t&&"PUT"!==t&&"PATCH"!==t||(n.body=JSON.stringify(i)),r.timeout){const e=new AbortController;n.signal=e.signal,setTimeout(()=>e.abort(),r.timeout)}const a=Date.now();try{const e=await fetch(s,n),i=Date.now()-a;if(this.updateRateLimitInfo(e),!e.ok){const t=await this.handleErrorResponse(e);throw this.emit("error",t),t}const r=await e.json();return this.emit("response",{url:s,method:t,status:e.status,responseTime:i,data:r}),r}catch(e){if("AbortError"===e.name)throw this.createNetworkError("TIMEOUT",`Request timeout after ${r.timeout}ms`,s,t);if("TypeError"===e.name&&e.message.includes("fetch"))throw this.createNetworkError("NETWORK_ERROR","Network error - please check your connection",s,t,e);throw e}}async handleErrorResponse(e){const t=e.headers.get("content-type");let s;try{s=t&&t.includes("application/json")?await e.json():{message:await e.text()}}catch(t){s={message:`HTTP ${e.status}`}}const i=new Error(s.message||`HTTP ${e.status}`);switch(i.status=e.status,i.code=s.code||e.status,i.url=e.url,i.data=s,e.status){case 400:i.type="VALIDATION_ERROR";break;case 401:i.type="AUTHENTICATION_ERROR";break;case 403:i.type="AUTHORIZATION_ERROR";break;case 404:i.type="NOT_FOUND";break;case 429:i.type="RATE_LIMIT_ERROR",i.retryAfter=parseInt(e.headers.get("Retry-After"))||60;break;case 500:i.type="SERVER_ERROR";break;case 502:case 503:case 504:i.type="SERVICE_UNAVAILABLE";break;default:i.type="UNKNOWN_ERROR"}return i}shouldRetry(e,t){if(t.attempts>=this.retryConfig.maxRetries)return!1;if(!t.options.retry)return!1;if(429===e.status||"RATE_LIMIT_ERROR"===e.type)return!1;const s=["SERVER_ERROR","SERVICE_UNAVAILABLE","TIMEOUT","NETWORK_ERROR"];return[500,502,503,504].includes(e.status)||s.includes(e.type)||s.includes(e.code)}async scheduleRetry(e){const t=this.calculateRetryDelay(e);await this.sleep(t),this.requestQueue.unshift(e)}calculateRetryDelay(e){const t=this.retryConfig.baseDelay*Math.pow(2,e.attempts-1),s=1e3*Math.random();return Math.min(t+s,this.retryConfig.maxDelay)}calculateRateLimitDelay(){if(!this.rateLimitInfo.resetTime)return 0;const e=Date.now(),t=1e3*this.rateLimitInfo.resetTime;return Math.max(0,t-e+1e3)}updateRateLimitInfo(e){const t=e.headers.get("X-RateLimit-Limit"),s=e.headers.get("X-RateLimit-Remaining"),i=e.headers.get("X-RateLimit-Reset");t&&(this.rateLimitInfo.limit=parseInt(t)),s&&(this.rateLimitInfo.remaining=parseInt(s)),i&&(this.rateLimitInfo.resetTime=parseInt(i))}sleep(e){return new Promise(t=>setTimeout(t,e))}getRateLimitInfo(){return{...this.rateLimitInfo}}getQueueStatus(){return{queueLength:this.requestQueue.length,isProcessing:this.isProcessingQueue}}clearQueue(){this.requestQueue.forEach(e=>{e.reject(new Error("Request queue cleared"))}),this.requestQueue=[],this.isProcessingQueue=!1}createNetworkError(e,t,s,i,r=null){const n=new Error(t);return n.code=e,n.url=s,n.method=i,r&&(n.originalError=r),n}destroy(){this.clearQueue(),this.removeAllListeners()}async shouldSkipEan(e){try{if(this.debug("[ViprosSDK] Bloom filter check for EAN:",e),await this.loadBloomFilter(),!this.bloomFilter)return this.debug("[ViprosSDK] No bloom filter available, allowing API call"),!1;const t=this.bloomFilter.test(e),s=!t;return this.debug(`[ViprosSDK] Bloom filter test for ${e}: ${t}, shouldSkip: ${s}`),s}catch(e){return this.debug("[ViprosSDK] Bloom filter error:",e?.message||e),!1}}async loadBloomFilter(){return this.bloomLoaded?this.bloomFilter:(this.bloomLoadPromise||(this.bloomLoadPromise=(async()=>{try{const e=this.getStorage();if(e){const t=e.getItem("vipros_bloom"),s=e.getItem("vipros_bloom_time");if(t&&s&&Date.now()-parseInt(s,10)<864e5)return this.bloomFilter=new $(this.base64ToUint8Array(t),{debug:this.isDebugEnabled()}),this.debug("[ViprosSDK] Bloom filter loaded from cache"),this.bloomLoaded=!0,this.bloomFilter}const t=await fetch(`${this.baseUrl}/sdk/bloom`,{headers:{Accept:"application/octet-stream","x-api-key":this.config.apiKey}});if(!t.ok)return this.debug("[ViprosSDK] Unable to download bloom filter, status:",t.status),this.bloomFilter=null,this.bloomLoaded=!0,this.bloomFilter;const s=await t.arrayBuffer(),i=new Uint8Array(s);return this.bloomFilter=new $(i,{debug:this.isDebugEnabled()}),e&&(e.setItem("vipros_bloom",this.uint8ArrayToBase64(i)),e.setItem("vipros_bloom_time",Date.now().toString())),this.debug("[ViprosSDK] Bloom filter downloaded and cached"),this.bloomLoaded=!0,this.bloomFilter}catch(e){return this.debug("[ViprosSDK] Bloom filter unavailable:",e?.message||e),this.bloomFilter=null,this.bloomLoaded=!0,this.bloomFilter}finally{this.bloomLoadPromise=null}})()),this.bloomLoadPromise)}uint8ArrayToBase64(e){if("undefined"!=typeof globalThis&&globalThis.Buffer)return globalThis.Buffer.from(e).toString("base64");let t="";for(let s=0;s<e.length;s+=32768){const i=e.subarray(s,s+32768);let r="";for(let e=0;e<i.length;e++)r+=String.fromCharCode(i[e]);t+=r}return btoa(t)}base64ToUint8Array(e){if("undefined"!=typeof globalThis&&globalThis.Buffer)return new Uint8Array(globalThis.Buffer.from(e,"base64"));const t=atob(e),s=t.length,i=new Uint8Array(s);for(let e=0;e<s;e++)i[e]=t.charCodeAt(e);return i}getStorage(){if("undefined"==typeof window||!window.localStorage)return null;try{const e="__vipros_storage_test__";return window.localStorage.setItem(e,"1"),window.localStorage.removeItem(e),window.localStorage}catch(e){return this.debug("[ViprosSDK] localStorage unavailable:",e?.message||e),null}}debug(...e){this.isDebugEnabled()}isDebugEnabled(){return Boolean(this.config&&this.config.debug)}}var N=Object.freeze({__proto__:null,default:x});class z extends a{constructor(e=3e5){super(),("number"!=typeof e||isNaN(e)||e<0)&&(e=3e5),this.cacheTimeout=e,this.memoryCache=new Map,this.setupCleanupInterval()}get(e,t=!0){const s=this.buildKey(e);let i=this.memoryCache.get(s);return i&&this.isValidCacheEntry(i)?(i.hits=(i.hits||0)+1,i.lastAccessTime=Date.now(),this.emit("hit",{key:e,source:"memory"}),i.data):(this.emit("miss",{key:e}),null)}set(e,t,s={}){const i=this.buildKey(e),r=this.createCacheEntry(t,s);this.memoryCache.set(i,r),this.emit("set",{key:e,size:this.estimateSize(t)}),this.enforceCacheLimits()}createCacheEntry(e,t={}){const s=Date.now(),i=t.ttl||this.cacheTimeout;return{data:e,timestamp:s,expires:i>0?s+i:null,hits:0,lastAccessTime:s,size:this.estimateSize(e),tags:t.tags||[],version:t.version||"3.0.0"}}isValidCacheEntry(e){return!(!e||"object"!=typeof e)&&(!(!e.timestamp||!e.data)&&!(e.expires&&Date.now()>e.expires))}estimateSize(e){try{return JSON.stringify(e).length}catch(e){return 0}}buildKey(e){return`vipros_sdk_${e}`}has(e){const t=this.buildKey(e);if(this.memoryCache.has(t)){const e=this.memoryCache.get(t);return this.isValidCacheEntry(e)}return!1}delete(e){const t=this.buildKey(e),s=this.memoryCache.delete(t);return s&&this.emit("delete",{key:e}),s}clear(){const e=this.memoryCache.size;this.memoryCache.clear(),this.emit("clear",{memorySize:e})}size(){return this.memoryCache.size}getStats(){const e={entries:this.memoryCache.size,totalSize:0,avgSize:0};for(const[,t]of this.memoryCache)e.totalSize+=t.size||0;return e.entries>0&&(e.avgSize=Math.round(e.totalSize/e.entries)),{memory:e}}enforceCacheLimits(){const e=10485760;this.memoryCache.size>100&&this.evictLeastRecentlyUsed(this.memoryCache.size-100);let t=0;for(const[,e]of this.memoryCache)t+=e.size||0;t>e&&this.evictLargestEntries(t-e)}evictLeastRecentlyUsed(e){Array.from(this.memoryCache.entries()).map(([e,t])=>({key:e,lastAccess:t.lastAccessTime||0})).sort((e,t)=>e.lastAccess-t.lastAccess).slice(0,e).forEach(({key:e})=>{this.memoryCache.delete(e)}),this.emit("lru_eviction",{count:e})}evictLargestEntries(e){const t=Array.from(this.memoryCache.entries()).map(([e,t])=>({key:e,entry:t})).sort((e,t)=>(t.entry.size||0)-(e.entry.size||0));let s=0,i=0;for(const{key:r,entry:n}of t){if(s>=e)break;this.memoryCache.delete(r),s+=n.size||0,i++}this.emit("size_eviction",{evicted:i,freedSize:s})}setupCleanupInterval(){"undefined"!=typeof window&&setInterval(()=>{this.cleanupExpiredEntries()},6e4)}cleanupExpiredEntries(){let e=0;const t=Date.now();for(const[s,i]of this.memoryCache)i.expires&&t>i.expires&&(this.memoryCache.delete(s),e++);e>0&&this.emit("cleanup",{cleaned:e})}destroy(){this.clear(),this.removeAllListeners()}}class K extends a{constructor(e,t,s={}){super(),this.apiClient=e,this.cacheService=t,this.config={debug:s.debug||!1,retryDelayMs:5e3,maxRetries:2,...s},this.stats={attempted:0,successful:0,failed:0,skipped:0,rateLimited:0,errors:[]}}syncProductInBackground(e,t){e&&t?this.performSync(e,t).catch(e=>{this.config.debug}):this.config.debug}async performSync(e,t,s=0){this.stats.attempted++;try{const s=await this.apiClient.syncProduct(e,t);if(200===s.code)return this.stats.successful++,this.emit("syncSuccess",{ean:e,productUrl:t,result:s,timestamp:new Date}),this.config.debug,{status:"success",result:s};if(202===s.code)return this.stats.skipped++,this.emit("syncSkipped",{ean:e,reason:"server_cooldown",remaining_hours:s.remaining_hours,next_sync_at:s.next_sync_at}),this.config.debug,{status:"skipped",reason:"server_cooldown"};throw new Error(`API returned status ${s.code}: ${s.message||"Unknown error"}`)}catch(i){return this.handleSyncError(e,t,i,s)}}handleSyncError(e,t,s,i){this.stats.failed++;const r=this.categorizeError(s);return"RATE_LIMIT"===r?(this.stats.rateLimited++,this.emit("syncRateLimited",{ean:e,productUrl:t,error:s,retryAfter:s.retryAfter||60}),this.config.debug,{status:"rate_limited",error:s.message}):"NETWORK_ERROR"===r&&i<this.config.maxRetries?(this.config.debug,setTimeout(()=>{this.performSync(e,t,i+1).catch(()=>{})},this.config.retryDelayMs),{status:"retrying",attempt:i+1}):(this.logError(e,s,r),this.emit("syncError",{ean:e,productUrl:t,error:s,errorType:r,retryCount:i}),this.config.debug,{status:"error",error:s.message,errorType:r})}categorizeError(e){return 429===e.status||"RATE_LIMIT_ERROR"===e.type?"RATE_LIMIT":e.status>=500||"SERVER_ERROR"===e.type?"SERVER_ERROR":"NETWORK_ERROR"===e.code||"NetworkError"===e.name?"NETWORK_ERROR":400===e.status||"VALIDATION_ERROR"===e.type?"VALIDATION_ERROR":"UNKNOWN"}logError(e,t,s){this.stats.errors.push({ean:e,error:t.message,type:s,timestamp:Date.now()}),this.stats.errors.length>100&&(this.stats.errors=this.stats.errors.slice(-50))}getSyncStats(){return{...this.stats,successRate:this.stats.attempted>0?(this.stats.successful/this.stats.attempted*100).toFixed(2)+"%":"0%"}}clearSyncStats(){this.stats={attempted:0,successful:0,failed:0,skipped:0,rateLimited:0,errors:[]}}async forceSyncNow(e,t){return this.performSyncWithForce(e,t)}async performSyncWithForce(e,t){this.stats.attempted++;try{const s=await this.apiClient.syncProduct(e,t,!0);if(200===s.code)return this.stats.successful++,this.emit("syncSuccess",{ean:e,productUrl:t,result:s,forced:!0,timestamp:new Date}),{status:"success",result:s,forced:!0};throw new Error(`API returned status ${s.code}: ${s.message||"Unknown error"}`)}catch(s){return this.stats.failed++,this.logError(e,s,"forced_sync"),this.emit("syncError",{ean:e,productUrl:t,error:s,forced:!0}),{status:"error",error:s.message,forced:!0}}}destroy(){this.clearSyncStats(),this.removeAllListeners()}}class ViprosSDK extends a{constructor(){if(super(),this.version="3.0.0-unified",this.isInitialized=!1,this.config={apiKey:null,debug:!1,syncEnabled:!0,inlineSyncEnabled:!0,disableBackgroundSync:!0,containerSelector:"[data-ean]",autoScan:!0},this._apiClient=null,this._cacheService=null,this._syncService=null,this._servicesInitialized=!1,this.stats={version:this.version,componentsRegistered:0,componentsActive:0,offersLoaded:0,errors:0,cacheHits:0,apiCalls:0,syncAttempts:0,syncSuccess:0},this.cache=new Map,this.eventListeners=new Map,ViprosSDK.instance)return ViprosSDK.instance;ViprosSDK.instance=this}static getInstance(){return ViprosSDK.instance||(ViprosSDK.instance=new ViprosSDK),ViprosSDK.instance}init(e={}){return this.isInitialized?(this.debugLog("SDK déjà initialisé"),this):(this.config=n.create({...this.config,...e}),this.debugLog(`🚀 Initialisation VIPros SDK v${this.version}`),this.debugLog("Configuration:",this.config),this.registerWebComponents(),this.config.autoScan&&this.scanAndConvert(),this.isInitialized=!0,this.emitEvent("sdk-ready",{version:this.version,config:this.config}),this.debugLog("🎯 SDK initialisé avec lazy loading - services créés à la demande"),this)}get apiClient(){return this._apiClient||(this.debugLog("📡 Création lazy d'ApiClient"),this._apiClient=new x(this.config)),this._apiClient}get cacheService(){return this._cacheService||(this.debugLog("💾 Création lazy de CacheService"),this._cacheService=new z(this.config.cacheTimeout||3e5)),this._cacheService}get syncService(){return!this._syncService&&this.config.syncEnabled&&(this.debugLog("🔄 Création lazy d'EanSyncService"),this._syncService=new K(this.apiClient,this.cacheService,this.config),this.setupSyncEvents()),this._syncService}initializeServicesEager(){this.debugLog("🚀 Initialisation eager de tous les services...");const e=this.apiClient,t=this.cacheService,s=this.syncService;return this._servicesInitialized=!0,this.debugLog("✅ Tous les services initialisés (eager)"),{api:e,cache:t,sync:s}}setupSyncEvents(){this.syncService&&(this.syncService.on("syncSuccess",e=>{this.stats.syncSuccess++,this.emit("syncSuccess",e)}),this.syncService.on("syncSkipped",e=>{this.emit("syncSkipped",e)}),this.syncService.on("syncError",e=>{this.emit("syncError",e)}),this.syncService.on("syncRateLimited",e=>{this.emit("syncRateLimited",e)}),this.debugLog("Événements de synchronisation connectés"))}getCacheService(){return this.cacheService}syncProductInBackground(e,t){this.config.disableBackgroundSync?this.debugLog("Sync en arrière-plan désactivée (disableBackgroundSync=true)"):this.syncService?(this.stats.syncAttempts++,this.debugLog(`Déclenchement sync pour EAN ${e}`),this.syncService.syncProductInBackground(e,t)):this.debugLog("Sync demandée mais service non disponible")}registerWebComponents(){customElements.get("vipros-offer-card")||(r.setSDKInstance(this),customElements.define("vipros-offer-card",r),this.stats.componentsRegistered++,this.debugLog("✅ vipros-offer-card registered"))}scanAndConvert(){const e=document.querySelectorAll(this.config.containerSelector);this.debugLog(`🔍 Scan: ${e.length} containers data-ean trouvés`),e.forEach(e=>{const t=e.getAttribute("data-ean"),s=e.getAttribute("data-price");if(t){const i=document.createElement("vipros-offer-card");i.setAttribute("ean",t),s&&i.setAttribute("price",s),e.parentNode.replaceChild(i,e),this.debugLog(`🔄 Converti data-ean="${t}" vers Web Component`)}})}getApiClient(){return this.apiClient}getServicesStatus(){return{apiClientInitialized:!!this._apiClient,cacheServiceInitialized:!!this._cacheService,syncServiceInitialized:!!this._syncService,allServicesEager:this._servicesInitialized}}async getProductData(e){const t=`product_${e}`;if(this.cache.has(t)){const s=this.cache.get(t);if(Date.now()-s.timestamp<this.config.cacheTimeout)return this.stats.cacheHits++,this.debugLog(`💾 Cache hit for EAN ${e}`),s.data}try{this.stats.apiCalls++;const s=await this.apiClient.getCatalogItemByEan(e),i=s?{code:200,item:s}:{code:404,item:null};return s&&this.cache.set(t,{data:i,timestamp:Date.now()}),this.debugLog(`📡 API data loaded for EAN ${e} (optimized route)`),i}catch(t){throw this.stats.errors++,this.debugLog(`❌ Erreur API pour EAN ${e}:`,t),t}}emitEvent(e,t={}){const s=`vipros-${e}`,i=new CustomEvent(s,{detail:t,bubbles:!0,cancelable:!0});document.dispatchEvent(i),this.debugLog(`📤 Event: ${s}`,t)}on(e,t){const s=`vipros-${e}`;document.addEventListener(s,t),this.eventListeners.has(s)||this.eventListeners.set(s,[]),this.eventListeners.get(s).push(t)}off(e,t){const s=`vipros-${e}`;if(document.removeEventListener(s,t),this.eventListeners.has(s)){const e=this.eventListeners.get(s),i=e.indexOf(t);i>-1&&e.splice(i,1)}}clearCache(){this.cache.clear(),this.debugLog("🗑️ Cache vidé")}refreshAll(){const e=document.querySelectorAll("vipros-offer-card");e.forEach(e=>{e.refresh&&"function"==typeof e.refresh&&e.refresh()}),this.debugLog(`🔄 Refresh de ${e.length} composants`)}getStats(){return this.stats.componentsActive=document.querySelectorAll("vipros-offer-card").length,{...this.stats}}debugLog(e,t=null){this.config.debug}destroy(){this.eventListeners.forEach((e,t)=>{e.forEach(e=>{document.removeEventListener(t,e)})}),this.eventListeners.clear(),this.cache.clear(),this._apiClient&&(this.debugLog("🧹 Nettoyage ApiClient"),this._apiClient=null),this._cacheService&&(this.debugLog("🧹 Nettoyage CacheService"),this._cacheService=null),this._syncService&&(this.debugLog("🧹 Nettoyage SyncService"),this._syncService=null),this._servicesInitialized=!1,this.isInitialized=!1,this.debugLog("🔥 SDK détruit avec nettoyage des services lazy")}}const F=new ViprosSDK;return"undefined"!=typeof window&&(window.ViprosSDK=F),F}();"undefined"!=typeof window&&void 0!==ViprosSDKBundle&&(window.ViprosSDK=ViprosSDKBundle);
1
+ /*! VIPros SDK v3.0.0-unified - Production Minified - 2026-02-11T13:45:27.756Z */
2
+ var ViprosSDKBundle=function(){"use strict";class e{constructor(e=!1){this.debug=e,this.templates=new Map,this.baseUrl=this.detectBaseUrl()}detectBaseUrl(){const e=window.location.origin;return window.location.hostname.includes("ddev.site"),e+"/api/sdk/components/templates"}async loadTemplate(e){if(this.templates.has(e))return this.templates.get(e);try{const t=await fetch(`${this.baseUrl}/${e}.html`);if(!t.ok)throw new Error(`Template ${e} not found: ${t.status}`);const s=await t.text();return this.templates.set(e,s),s}catch(t){return this.getFallbackTemplate(e)}}async render(e,t={}){const s=await this.loadTemplate(e);return this.interpolate(s,t)}interpolate(e,t){let s=this.processConditionalBlocks(e,t);return s=s.replace(/\{\{([^}#/][^}]*)\}\}/g,(e,s)=>{const i=this.resolveNestedKey(t,s.trim());return null!==i?i:""}),s}resolveNestedKey(e,t){return t.startsWith("#")||t.startsWith("/")?"":t.split(".").reduce((e,t)=>e&&void 0!==e[t]?e[t]:null,e)}processConditionalBlocks(e,t){let s=e,i=0;for(;(s.includes("{{#if")||s.includes("{{#unless"))&&(i++,!(i>10));){const e=s;if(s=this.processIfBlocks(s,t),s=this.processUnlessBlocks(s,t),s===e)break}return s}processIfBlocks(e,t){return e.replace(/\{\{#if\s+([^}]+)\}\}((?:(?!\{\{#if)[\s\S])*?)\{\{\/if\}\}/g,(e,s,i)=>{const r=this.resolveNestedKey(t,s.trim()),n=Boolean(r),a=i.split(/\{\{else\}\}/);return 2===a.length?n?a[0]:a[1]:n?i:""})}processUnlessBlocks(e,t){return e.replace(/\{\{#unless\s+([^}]+)\}\}((?:(?!\{\{#unless)[\s\S])*?)\{\{\/unless\}\}/g,(e,s,i)=>{const r=this.resolveNestedKey(t,s.trim());return!Boolean(r)?i:""})}handleConditional(e,t,s){const i=t.split(" ")[1],r=this.resolveNestedKey(e,i),n=Boolean(r);return(s?n:!n)?"":"\x3c!-- condition-false --\x3e"}getFallbackTemplate(e){return{CashbackTemplate:'\n <div class="vipros-offer-card cashback-mode">\n <div class="offer-content">\n <div class="main-value">\n <span class="amount">{{cashback.value}}</span>\n <span class="currency">€</span>\n <span class="label">remboursés</span>\n </div>\n </div>\n </div>\n ',VIPointsTemplate:'\n <div class="vipros-offer-card vipoints-mode">\n <div class="offer-content">\n <div class="main-value">\n <span class="amount">{{vipoints.perTenEuros}}</span>\n <span class="label">VIPoints</span>\n </div>\n </div>\n </div>\n ',LoadingTemplate:'\n <div class="vipros-offer-card loading-state">\n <div class="loading-text">Recherche...</div>\n </div>\n ',ErrorTemplate:'\n <div class="vipros-offer-card error-state">\n <div class="error-text">{{message}}</div>\n <div class="debug-notice">Erreur affichée car le mode debug est activé</div>\n </div>\n '}[e]||'<div class="vipros-offer-card">Template not found</div>'}async preloadTemplates(){const e=["CashbackTemplate","VIPointsTemplate","LoadingTemplate","ErrorTemplate"].map(e=>this.loadTemplate(e).catch(e=>(this.debug,null)));await Promise.all(e),this.debug}clearCache(){this.templates.clear()}}class t{static transform(e,t=null){if(!e)return null;const s=Boolean(e.cashback?.value>0),i=e.brand?.generosity_rate||0,r=this.calculateVIPoints(i,t);return{id:e.id||"not_found",ean:e.ean,name:e.name||"Produit inconnu",price:t,brand:this.transformBrandData(e.brand),cashback:this.transformCashbackData(e.cashback),vipoints:r,hasCashback:s,viprosLink:this.buildViprosLink(e),vipointsImageUrl:null}}static transformBrandData(e){if(!e)return{name:"Marque inconnue",displayName:null,logoUrl:null,generosityRate:0};const t=e.name&&"Marque inconnue"!==e.name?e.name:null;return{name:e.name||"Marque inconnue",displayName:t,logoUrl:e.logo_url||null,generosityRate:e.generosity_rate||0}}static transformCashbackData(e){return e?{value:e.value||0,name:e.name||null,imageUrl:e.image_url||null,startDate:e.start_date||null,endDate:e.end_date||null}:{value:0,name:null,imageUrl:null,startDate:null,endDate:null}}static calculateVIPoints(e,t){let s=0,i=!1,r=!1;return e>0&&(i=!0,t&&t>0?(s=Math.floor(e*t/10),r=!0):(s=1,r=!1)),{perTenEuros:s,generosityRate:e,hasBonus:i,showExact:r}}static determineDisplayMode(e){return e?e.hasCashback?"cashback":e.vipoints.hasBonus?"vipoints":"empty":"empty"}static validate(e){if(!e)return{isValid:!1,errors:["No data provided"]};const t=[];return e.ean||t.push("EAN is required"),e.hasCashback&&!e.cashback.value&&t.push("Cashback value is required when hasCashback is true"),e.vipoints.hasBonus&&!e.vipoints.generosityRate&&t.push("Generosity rate is required when VIPoints bonus is available"),{isValid:0===t.length,errors:t}}static prepareTemplateData(e,t=null){return e?{...e,vipointsImageUrl:t||this.getDefaultVIPointsImageUrl()}:null}static buildViprosLink(e){const t=e.vipros_link||"https://vipros.fr",s=this.getSalesPointName(e),i="undefined"!=typeof window?window.location.href:"",r=new URL(t);return s&&r.searchParams.set("origin",s),i&&r.searchParams.set("origin_url",i),r.toString()}static getSalesPointName(e){if(e.sales_points&&Array.isArray(e.sales_points)){const t=e.sales_points.find(e=>e.name);if(t)return t.name}if("undefined"!=typeof window){return window.location.hostname.replace(/^www\./,"").replace(/\./g," ").split(" ")[0]}return null}static getDefaultVIPointsImageUrl(){return"/api/sdk/assets/image-vipoints.jpg"}}class s{static resolveDisplayMode(e){return e?e.hasCashback?"cashback":e.vipoints.hasBonus?"vipoints":"empty":"empty"}static resolveTemplateName(e){return{cashback:"CashbackTemplate",vipoints:"VIPointsTemplate",loading:"LoadingTemplate",error:"ErrorTemplate",empty:null,hidden:null}[e]||null}static shouldDisplay(e){return!["empty","hidden"].includes(e)}static resolveContainerClass(e){return`vipros-offer-card ${{cashback:"cashback-mode",vipoints:"vipoints-mode",loading:"loading-state",error:"error-state",empty:"empty-state",hidden:"hidden-state"}[e]||""}`}static validateDisplayMode(e){return["cashback","vipoints","loading","error","empty","hidden"].includes(e)?e:"error"}static analyze(e,t={}){const{isLoading:s=!1,error:i=null,debug:r=!1}=t;if(i)return r?{mode:"error",template:"ErrorTemplate",shouldDisplay:!0,containerClass:this.resolveContainerClass("error"),data:{message:i.message||"Une erreur est survenue",debugMode:!0}}:{mode:"hidden",template:null,shouldDisplay:!1,containerClass:this.resolveContainerClass("hidden"),data:{}};if(s)return{mode:"loading",template:"LoadingTemplate",shouldDisplay:!0,containerClass:this.resolveContainerClass("loading"),data:{}};const n=this.resolveDisplayMode(e),a=this.resolveTemplateName(n),o=this.shouldDisplay(n),c=this.resolveContainerClass(n);return{mode:this.validateDisplayMode(n),template:a,shouldDisplay:o,containerClass:c,data:o?e:{}}}static hasMinimumRequiredData(e){return!!e&&(!!e.ean&&(e.hasCashback||e.vipoints.hasBonus))}static suggestDataImprovements(e){if(!e)return["Product data is required"];const t=[];return e.name&&"Produit inconnu"!==e.name||t.push("Product name could be improved"),e.hasCashback&&!e.cashback.imageUrl&&t.push("Cashback image would improve visual appeal"),!e.price&&e.vipoints.hasBonus&&t.push("Price would enable exact VIPoints calculation"),e.brand.displayName||t.push("Brand name would improve VIPoints messaging"),t}}class i{constructor(e){this.element=e,this.listeners=new Map}emit(e,t={}){const s=new CustomEvent(e,{detail:t,bubbles:!0,cancelable:!0});this.element.dispatchEvent(s),this.element.getAttribute("debug")}emitOfferLoaded(e,t){this.emit("vipros-offer-loaded",{product:e,ean:t,timestamp:Date.now()})}emitError(e,t){this.emit("vipros-offer-error",{error:{message:e.message||"Unknown error",type:e.constructor.name,stack:e.stack},ean:t,timestamp:Date.now()})}emitOfferClick(e,t,s){this.emit("vipros-offer-click",{url:e,product:t,ean:s,timestamp:Date.now()})}emitSyncStarted(e,t){this.emit("vipros-sync-started",{ean:e,url:t,timestamp:Date.now()})}emitSyncSuccess(e,t){this.emit("vipros-sync-success",{ean:e,result:t,timestamp:Date.now()})}emitSyncError(e,t){this.emit("vipros-sync-error",{ean:e,error:{message:t.message||"Sync error",type:t.constructor.name},timestamp:Date.now()})}attachLinkListeners(e,t,s){e.querySelectorAll("a[href]").forEach(e=>{const i=i=>{this.emitOfferClick(e.href,t,s),window.gtag&&window.gtag("event","vipros_offer_click",{ean:s,url:e.href,product_name:t?.name})};e.addEventListener("click",i),this.listeners.has("linkClicks")||this.listeners.set("linkClicks",[]),this.listeners.get("linkClicks").push({link:e,handler:i})})}cleanup(){this.listeners.has("linkClicks")&&this.listeners.get("linkClicks").forEach(({link:e,handler:t})=>{e.removeEventListener("click",t)}),this.listeners.clear()}enableGlobalDebugging(){["vipros-offer-loaded","vipros-offer-error","vipros-offer-click","vipros-sync-started","vipros-sync-success","vipros-sync-error"].forEach(e=>{document.addEventListener(e,e=>{})})}static emit(e,t,s={}){new i(e).emit(t,s)}static emitOfferLoaded(e,t,s){new i(e).emitOfferLoaded(t,s)}static emitError(e,t,s){new i(e).emitError(t,s)}}class r extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this.templateLoader=new e,this.eventManager=new i(this),this.state={isLoading:!1,productData:null,error:null,apiClient:null},this.init=this.init.bind(this),this.loadProduct=this.loadProduct.bind(this),this.render=this.render.bind(this)}static get observedAttributes(){return["ean","price","api-base-url","api-key","primary-color","text-color","background-color","card-bonus-bg","card-bonus-color"]}get ean(){return this.getAttribute("ean")||this.getConfigValue("ean")}get price(){const e=parseFloat(this.getAttribute("price"))||0;if(e>0)return e;const t=this.getConfigValue("price");return t&&parseFloat(t)>0?parseFloat(t):null}get apiBaseUrl(){return this.getConfigValue("apiBaseUrl")||this.getAttribute("api-base-url")||this.detectFallbackApiBaseUrl()}get apiKey(){return this.getConfigValue("apiKey")||this.getAttribute("api-key")}get primaryColor(){return this.getAttribute("primary-color")||this.getConfigValue("primaryColor")}get textColor(){return this.getAttribute("text-color")||this.getConfigValue("textColor")}get backgroundColor(){return this.getAttribute("background-color")||this.getConfigValue("backgroundColor")}get cardBonusBg(){return this.getAttribute("card-bonus-bg")||this.getConfigValue("cardBonusBg")}get cardBonusColor(){return this.getAttribute("card-bonus-color")||this.getConfigValue("cardBonusColor")}getConfigValue(e){const t=this.getSDKInstance();return t?.config?.[e]||null}getSDKInstance(){return"undefined"!=typeof window?window.ViprosSDK:null}detectFallbackApiBaseUrl(){if("undefined"==typeof window)return this.log("[ViprosOfferCard] No window object - defaulting to production API"),"https://msys.vipros.fr/api";try{if(!window.location||"string"!=typeof window.location.hostname)return this.log("[ViprosOfferCard] Invalid window.location - defaulting to production API"),"https://msys.vipros.fr/api";const e=window.location.protocol||"https:",t=window.location.hostname.toLowerCase();return t&&0!==t.length?"file:"===e||"localhost"===t||t.startsWith("127.0.0.1")||t.startsWith("0.0.0.0")?(this.log("[ViprosOfferCard] Local development detected - using DDEV fallback"),"https://vipros-connect.ddev.site/api"):"vipros-connect.ddev.site"===t?`${e}//${t}/api`:"msys.preprod.vipros.fr"===t?`${e}//msys.preprod.vipros.fr/api`:t.endsWith(".vipros.fr")?(this.log(`[ViprosOfferCard] VIPros subdomain detected: ${t}`),`${e}//${t}/api`):(this.log(`[ViprosOfferCard] Unknown domain: ${t} - defaulting to production API`),"https://msys.vipros.fr/api"):(this.log("[ViprosOfferCard] Empty hostname - defaulting to production API"),"https://msys.vipros.fr/api")}catch(e){return this.log(`[ViprosOfferCard] Error detecting API base URL: ${e.message} - defaulting to production`),"https://msys.vipros.fr/api"}}connectedCallback(){this.log("[ViprosOfferCard] Component connected"),this.init()}attributeChangedCallback(e,t,s){t!==s&&this.isConnected&&("ean"===e?(this.log(`[ViprosOfferCard] EAN changed: ${t} → ${s}`),this.loadProduct()):["primary-color","text-color","background-color","gift-icon-color","gift-card-bonus-bg","gift-card-bonus-color","vipoints-bonus-bg","vipoints-bonus-color"].includes(e)&&(this.log(`[ViprosOfferCard] Color changed: ${e} = ${s}`),this.updateCustomColors()))}disconnectedCallback(){this.log("[ViprosOfferCard] Component disconnected"),this.cleanup()}async init(){try{this.loadGoogleFonts(),await this.loadStyles(),this.updateCustomColors(),await this.initApiClient(),await this.templateLoader.preloadTemplates(),this.ean?await this.loadProduct():this.setError(new Error("EAN requis pour afficher une offre VIPros"))}catch(e){this.logError("[ViprosOfferCard] Init error:",e),this.setError(e)}}loadGoogleFonts(){["https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;500;600;700&display=swap","https://fonts.googleapis.com/css2?family=Encode+Sans+Condensed:wght@100;200;300;400;500;600;700;800;900&display=swap"].forEach(e=>{if(!document.querySelector(`link[href="${e}"]`)){const t=document.createElement("link");t.rel="stylesheet",t.href=e,t.crossOrigin="anonymous",document.head.appendChild(t)}})}async loadStyles(){try{const e=this.templateLoader.baseUrl.replace("/components/templates","/components/styles/offer-card.css"),t=await fetch(e);if(t.ok){const e=await t.text(),s=document.createElement("style");s.textContent=e,this.shadowRoot.appendChild(s)}else this.injectFallbackStyles()}catch(e){this.logError("[ViprosOfferCard] CSS loading failed, using fallback"),this.injectFallbackStyles()}}updateCustomColors(){if(!this.shadowRoot)return;const e=this.shadowRoot.host,t={};this.primaryColor&&(t["--vipros-primary"]=this.primaryColor,t["--vipros-text-accent"]=this.primaryColor),this.textColor&&(t["--vipros-text-main"]=this.textColor),this.backgroundColor&&(t["--vipros-background"]=this.backgroundColor),this.cardBonusBg&&(t["--card-bonus-bg"]=this.cardBonusBg),this.cardBonusColor&&(t["--card-bonus-color"]=this.cardBonusColor),Object.entries(t).forEach(([t,s])=>{e.style.setProperty(t,s)}),this.log("[ViprosOfferCard] Custom colors applied:",t)}injectFallbackStyles(){const e=document.createElement("style");e.textContent="\n .vipros-offer-card { \n display: block; \n padding: 20px; \n background: #e8ecf8; \n border-radius: 12px; \n font-family: sans-serif; \n }\n .loading-content, .error-content { \n text-align: center; \n padding: 40px; \n }\n ",this.shadowRoot.appendChild(e)}log(e,...t){const s=this.getSDKInstance();s&&s.config&&s.config.debug}logError(e,...t){const s=this.getSDKInstance();s&&s.config&&s.config.debug}async initApiClient(){const e=this.getSDKInstance();if(e&&e.getApiClient)this.state.apiClient=e.getApiClient(),this.log("[ViprosOfferCard] Using shared SDK ApiClient");else{const{default:e}=await Promise.resolve().then(function(){return N});this.state.apiClient=new e({apiBaseUrl:this.apiBaseUrl,apiKey:this.apiKey}),this.log("[ViprosOfferCard] Created local ApiClient")}}async loadProduct(){if(this.ean&&!this.state.isLoading)if(this.state.apiClient){this.setLoading(!0);try{this.log(`[ViprosOfferCard] Loading product: ${this.ean}`);const e=this.getSDKInstance(),s={timeout:5e3};e?.config?.inlineSyncEnabled&&(s.enableInlineSync=!0,s.productUrl=window.location.href,this.log(`[ViprosOfferCard] Inline sync enabled for EAN ${this.ean}`));const i=await this.state.apiClient.get("/catalog/items",{ean:this.ean,items_per_page:1},s),r=i?.metadata?.bloomFilter,n=Boolean(this.getConfigValue("debug")||"true"===this.getAttribute("debug"));if(r?.skipped){if(this.log(`[ViprosOfferCard] Bloom filter skipped API call for EAN ${this.ean}`),n){const e=new Error("404 | Produit introuvable (Bloom filter)");e.status=404,e.type="BLOOM_FILTER_NOT_FOUND",e.data={ean:this.ean,reason:r.reason||"NOT_IN_FILTER"},this.setError(e)}else this.setProductData(null);return}const a=i?.sdk_metadata?.sync;if(a&&this.getConfigValue("debug")&&this.log("[ViprosOfferCard] Sync metadata:",a),i.items&&i.items.length>0){const e=t.transform(i.items[0],this.price);e.vipointsImageUrl=this.getVIPointsImageUrl(),this.setProductData(e),this.log(`[ViprosOfferCard] Product loaded: ${e.name}`);null!=a?this.log(`[ViprosOfferCard] Skipping background sync (inline sync was attempted, status: ${a.reason||"unknown"})`):this.triggerBackgroundSync(),this.eventManager.emitOfferLoaded(e,this.ean)}else this.log(`[ViprosOfferCard] No product found for EAN: ${this.ean}`),this.setProductData(null)}catch(e){if(this.logError(`[ViprosOfferCard] Error loading EAN ${this.ean}:`,e),429===e.status||"RATE_LIMIT_ERROR"===e.type){const e=new Error("API rate limit exceeded - Trop de requêtes simultanées");e.status=429,e.type="RATE_LIMIT_ERROR",this.setError(e)}else this.setError(e)}finally{this.setLoading(!1)}}else setTimeout(()=>this.loadProduct(),100)}setLoading(e){this.state.isLoading=e,this.render()}setProductData(e){this.state.productData=e,this.state.error=null}setError(e){this.state.error=e,this.state.productData=null,this.render(),this.eventManager.emitError(e,this.ean)}async render(){const e=s.analyze(this.state.productData,{isLoading:this.state.isLoading,error:this.state.error,debug:this.getConfigValue("debug")||!1});if(e.shouldDisplay){if(e.template){const t=await this.templateLoader.render(e.template,e.data);this.updateShadowContent(t),this.state.isLoading||this.attachEventListeners()}}else this.updateShadowContent('<div class="vipros-offer-card hidden"></div>')}async renderLoading(){await this.render()}updateShadowContent(e){const t=Array.from(this.shadowRoot.querySelectorAll("style")).map(e=>e.textContent);this.shadowRoot.replaceChildren();const s=document.createElement("div");for(s.innerHTML=e;s.firstChild;)this.shadowRoot.appendChild(s.firstChild);t.forEach(e=>{const t=document.createElement("style");t.textContent=e,this.shadowRoot.appendChild(t)})}attachEventListeners(){this.state.productData&&this.eventManager.attachLinkListeners(this.shadowRoot,this.state.productData,this.ean)}getVIPointsImageUrl(){return`${(this.apiBaseUrl||"").replace("/api","")}/api/sdk/assets/image-vipoints.jpg`}triggerBackgroundSync(){const e=this.getSDKInstance();e?.syncService&&setTimeout(()=>{this.log(`[ViprosOfferCard] Background sync for EAN ${this.ean}`),e.syncProductInBackground(this.ean,window.location.href)},100)}cleanup(){this.eventManager.cleanup(),this.state.apiClient=null,this.state.productData=null}}r.setSDKInstance=function(e){};class n{static create(e={}){const t=n.getDefaultConfig(),s=n.mergeConfig(t,e);return n.validateConfig(s)}static getDefaultConfig(){return{apiBaseUrl:n.detectApiBaseUrl(),apiKey:null,timeout:1e4,ean:null,price:null,primaryColor:null,textColor:null,backgroundColor:null,cardBonusBg:null,cardBonusColor:null,cacheTimeout:3e5,cachePrefix:"vipros_sdk_",maxCacheSize:100,containerSelector:"[data-ean]",eanAttribute:"data-ean",renderPosition:"replace",excludeSelectors:[".vipros-offer","[data-vipros-exclude]"],templates:{},styling:{theme:"minimal",customCSS:{},inlineStyles:!0,cssPrefix:"vipros-",responsive:!0},batchRequests:!0,lazyLoad:!0,maxConcurrentRequests:3,debounceDelay:300,hideOnError:!1,retryOnError:!0,gracefulDegradetion:!0,syncEnabled:!0,syncOptions:{cooldownTime:864e5,syncDelay:100,maxRetries:3,retryDelay:1e3},debug:!1,verbose:!1,logLevel:"warn",onReady:null,onOfferFound:null,onOfferRendered:null,onOfferLoaded:null,onError:null,features:{analyticsTracking:!1,performanceMonitoring:!1,a11yEnhancements:!0,seoOptimizations:!0},locale:"fr-FR",currency:"EUR",dateFormat:"DD/MM/YYYY",version:"1.0.0"}}static mergeConfig(e,t){return n.deepMerge(e,t)}static deepMerge(e,t){const s={...e};for(const[e,i]of Object.entries(t))null!=i&&(n.isObject(i)&&n.isObject(s[e])?s[e]=n.deepMerge(s[e],i):s[e]=i);return s}static isObject(e){return e&&"object"==typeof e&&!Array.isArray(e)}static validateConfig(e){const t=[];if(e.apiBaseUrl&&"string"==typeof e.apiBaseUrl)try{new URL(e.apiBaseUrl)}catch(e){t.push("apiBaseUrl must be a valid URL")}else t.push("apiBaseUrl must be a valid string");if(e.apiKey||t.push("apiKey is required"),e.apiKey&&"string"!=typeof e.apiKey&&t.push("apiKey must be a string"),e.timeout&&("number"!=typeof e.timeout||e.timeout<=0)&&t.push("timeout must be a positive number"),e.cacheTimeout&&("number"!=typeof e.cacheTimeout||e.cacheTimeout<0)&&t.push("cacheTimeout must be a non-negative number"),e.maxCacheSize&&("number"!=typeof e.maxCacheSize||e.maxCacheSize<=0)&&t.push("maxCacheSize must be a positive number"),e.containerSelector&&"string"!=typeof e.containerSelector&&t.push("containerSelector must be a string"),e.eanAttribute&&"string"!=typeof e.eanAttribute&&t.push("eanAttribute must be a string"),e.styling){const s=["minimal","branded","custom"];e.styling.theme&&!s.includes(e.styling.theme)&&t.push(`styling.theme must be one of: ${s.join(", ")}`),e.styling.customCSS&&!n.isObject(e.styling.customCSS)&&t.push("styling.customCSS must be an object")}e.maxConcurrentRequests&&("number"!=typeof e.maxConcurrentRequests||e.maxConcurrentRequests<=0)&&t.push("maxConcurrentRequests must be a positive number"),e.debounceDelay&&("number"!=typeof e.debounceDelay||e.debounceDelay<0)&&t.push("debounceDelay must be a non-negative number");const s=["error","warn","info","debug"];e.logLevel&&!s.includes(e.logLevel)&&t.push(`logLevel must be one of: ${s.join(", ")}`);const i=["onReady","onOfferFound","onOfferRendered","onOfferLoaded","onError"];for(const s of i)e[s]&&"function"!=typeof e[s]&&t.push(`${s} must be a function`);if(e.locale&&"string"!=typeof e.locale&&t.push("locale must be a string"),e.currency&&"string"!=typeof e.currency&&t.push("currency must be a string"),t.length>0){const e=new Error(`Configuration validation failed:\n${t.join("\n")}`);throw e.validationErrors=t,e}return n.processConfig(e)}static processConfig(e){const t={...e};if(t.apiBaseUrl=t.apiBaseUrl.replace(/\/$/,""),t.containerSelector.startsWith("[")||t.containerSelector.startsWith(".")||t.containerSelector.startsWith("#")||(t.containerSelector=`[${t.eanAttribute}]`),"debug"===t.logLevel?(t.debug=!0,t.verbose=!0):"info"===t.logLevel&&(t.debug=!0),t.styling.customCSS){const e={};for(const[s,i]of Object.entries(t.styling.customCSS)){e[s.startsWith("--")?s:`--vipros-${s}`]=i}t.styling.customCSS=e}return t.cachePrefix=`${t.cachePrefix}v${t.version.replace(/\./g,"_")}_`,t.derived={isProduction:!t.debug,shouldCache:t.cacheTimeout>0,shouldBatch:t.batchRequests&&t.maxConcurrentRequests>1,shouldLazyLoad:t.lazyLoad,hasCustomStyling:"custom"===t.styling.theme||Object.keys(t.styling.customCSS||{}).length>0},t}static createSecureConfig(e,t={}){const s={apiBaseUrl:t.apiBaseUrl,allowedFeatures:t.allowedFeatures,rateLimits:t.rateLimits,version:t.version};return n.create({...s,...e})}static validateRuntimeConfig(e){if(!e)throw new Error("Configuration is required");if(!e.derived)throw new Error("Configuration has not been processed");return!0}static getConfigSummary(e){return{version:e.version,apiBaseUrl:e.apiBaseUrl,theme:e.styling.theme,cacheEnabled:e.derived.shouldCache,debugMode:e.debug,features:Object.keys(e.features).filter(t=>e.features[t])}}static detectApiBaseUrl(e=!1){try{if("undefined"==typeof window)return"https://msys.vipros.fr/api";if(!window.location||"string"!=typeof window.location.hostname)return"https://msys.vipros.fr/api";const e=window.location.protocol||"https:",t=window.location.hostname.toLowerCase();return t&&0!==t.length?"file:"===e||"localhost"===t||t.startsWith("127.0.0.1")||t.startsWith("0.0.0.0")||t.includes(":")&&(t.includes("localhost")||t.includes("127.0.0.1"))?"https://vipros-connect.ddev.site/api":"vipros-connect.ddev.site"===t?`${e}//${t}/api`:"msys.preprod.vipros.fr"===t?`${e}//msys.preprod.vipros.fr/api`:t.endsWith(".vipros.fr")?`${e}//${t}/api`:(/^\d+\.\d+\.\d+\.\d+$/.test(t),"https://msys.vipros.fr/api"):"https://msys.vipros.fr/api"}catch(e){return"https://msys.vipros.fr/api"}}}class a{constructor(){this.events=new Map,this.maxListeners=10}on(e,t){if("function"!=typeof t)throw new TypeError("Callback must be a function");this.events.has(e)||this.events.set(e,[]);const s=this.events.get(e);return s.length,this.maxListeners,s.push(t),this}once(e,t){if("function"!=typeof t)throw new TypeError("Callback must be a function");const s=(...i)=>{this.off(e,s),t.apply(this,i)};return this.on(e,s)}off(e,t){if(!this.events.has(e))return this;if(!t)return this.events.delete(e),this;const s=this.events.get(e),i=s.indexOf(t);return-1!==i&&s.splice(i,1),0===s.length&&this.events.delete(e),this}emit(e,...t){if(!this.events.has(e))return!1;const s=this.events.get(e).slice();for(const e of s)try{e.apply(this,t)}catch(e){this.emit("error",e)}return!0}removeAllListeners(e=null){return e?this.events.delete(e):this.events.clear(),this}listenerCount(e){return this.events.has(e)?this.events.get(e).length:0}getMaxListeners(){return this.maxListeners}setMaxListeners(e){if("number"!=typeof e||e<0)throw new TypeError("Max listeners must be a non-negative number");return this.maxListeners=e,this}eventNames(){return Array.from(this.events.keys())}listeners(e){return this.events.has(e)?this.events.get(e).slice():[]}}var o=Uint8Array,c=Uint16Array,l=Int32Array,h=new o([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),u=new o([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),d=new o([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),p=function(e,t){for(var s=new c(31),i=0;i<31;++i)s[i]=t+=1<<e[i-1];var r=new l(s[30]);for(i=1;i<30;++i)for(var n=s[i];n<s[i+1];++n)r[n]=n-s[i]<<5|i;return{b:s,r:r}},m=p(h,2),g=m.b,f=m.r;g[28]=258,f[258]=28;for(var y=p(u,0).b,b=new c(32768),v=0;v<32768;++v){var C=(43690&v)>>1|(21845&v)<<1;C=(61680&(C=(52428&C)>>2|(13107&C)<<2))>>4|(3855&C)<<4,b[v]=((65280&C)>>8|(255&C)<<8)>>1}var w=function(e,t,s){for(var i=e.length,r=0,n=new c(t);r<i;++r)e[r]&&++n[e[r]-1];var a,o=new c(t);for(r=1;r<t;++r)o[r]=o[r-1]+n[r-1]<<1;if(s){a=new c(1<<t);var l=15-t;for(r=0;r<i;++r)if(e[r])for(var h=r<<4|e[r],u=t-e[r],d=o[e[r]-1]++<<u,p=d|(1<<u)-1;d<=p;++d)a[b[d]>>l]=h}else for(a=new c(i),r=0;r<i;++r)e[r]&&(a[r]=b[o[e[r]-1]++]>>15-e[r]);return a},S=new o(288);for(v=0;v<144;++v)S[v]=8;for(v=144;v<256;++v)S[v]=9;for(v=256;v<280;++v)S[v]=7;for(v=280;v<288;++v)S[v]=8;var E=new o(32);for(v=0;v<32;++v)E[v]=5;var k=w(S,9,1),L=w(E,5,1),R=function(e){for(var t=e[0],s=1;s<e.length;++s)e[s]>t&&(t=e[s]);return t},A=function(e,t,s){var i=t/8|0;return(e[i]|e[i+1]<<8)>>(7&t)&s},I=function(e,t){var s=t/8|0;return(e[s]|e[s+1]<<8|e[s+2]<<16)>>(7&t)},D=function(e){return(e+7)/8|0},T=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],_=function(e,t,s){var i=new Error(t||T[e]);if(i.code=e,Error.captureStackTrace&&Error.captureStackTrace(i,_),!s)throw i;return i},B=function(e,t,s,i){var r=e.length;if(!r||t.f&&!t.l)return s||new o(0);var n=!s,a=n||2!=t.i,c=t.i;n&&(s=new o(3*r));var l=function(e){var t=s.length;if(e>t){var i=new o(Math.max(2*t,e));i.set(s),s=i}},p=t.f||0,m=t.p||0,f=t.b||0,b=t.l,v=t.d,C=t.m,S=t.n,E=8*r;do{if(!b){p=A(e,m,1);var T=A(e,m+1,3);if(m+=3,!T){var B=e[(M=D(m)+4)-4]|e[M-3]<<8,U=M+B;if(U>r){c&&_(0);break}a&&l(f+B),s.set(e.subarray(M,U),f),t.b=f+=B,t.p=m=8*U,t.f=p;continue}if(1==T)b=k,v=L,C=9,S=5;else if(2==T){var O=A(e,m,31)+257,V=A(e,m+10,15)+4,P=O+A(e,m+5,31)+1;m+=14;for(var $=new o(P),x=new o(19),N=0;N<V;++N)x[d[N]]=A(e,m+3*N,7);m+=3*V;var z=R(x),K=(1<<z)-1,F=w(x,z,1);for(N=0;N<P;){var M,q=F[A(e,m,K)];if(m+=15&q,(M=q>>4)<16)$[N++]=M;else{var j=0,W=0;for(16==M?(W=3+A(e,m,3),m+=2,j=$[N-1]):17==M?(W=3+A(e,m,7),m+=3):18==M&&(W=11+A(e,m,127),m+=7);W--;)$[N++]=j}}var Q=$.subarray(0,O),H=$.subarray(O);C=R(Q),S=R(H),b=w(Q,C,1),v=w(H,S,1)}else _(1);if(m>E){c&&_(0);break}}a&&l(f+131072);for(var G=(1<<C)-1,X=(1<<S)-1,J=m;;J=m){var Y=(j=b[I(e,m)&G])>>4;if((m+=15&j)>E){c&&_(0);break}if(j||_(2),Y<256)s[f++]=Y;else{if(256==Y){J=m,b=null;break}var Z=Y-254;if(Y>264){var ee=h[N=Y-257];Z=A(e,m,(1<<ee)-1)+g[N],m+=ee}var te=v[I(e,m)&X],se=te>>4;te||_(3),m+=15&te;H=y[se];if(se>3){ee=u[se];H+=I(e,m)&(1<<ee)-1,m+=ee}if(m>E){c&&_(0);break}a&&l(f+131072);var ie=f+Z;if(f<H){var re=0-H,ne=Math.min(H,ie);for(re+f<0&&_(3);f<ne;++f)s[f]=i[re+f]}for(;f<ie;++f)s[f]=s[f-H]}}t.l=b,t.p=J,t.b=f,t.f=p,b&&(p=1,t.m=C,t.d=v,t.n=S)}while(!p);return f!=s.length&&n?function(e,t,s){return(null==s||s>e.length)&&(s=e.length),new o(e.subarray(t,s))}(s,0,f):s.subarray(0,f)},U=new o(0);function O(e,t){var s,i,r=function(e){31==e[0]&&139==e[1]&&8==e[2]||_(6,"invalid gzip data");var t=e[3],s=10;4&t&&(s+=2+(e[10]|e[11]<<8));for(var i=(t>>3&1)+(t>>4&1);i>0;i-=!e[s++]);return s+(2&t)}(e);return r+8>e.length&&_(6,"invalid gzip data"),B(e.subarray(r,-8),{i:2},new o((i=(s=e).length,(s[i-4]|s[i-3]<<8|s[i-2]<<16|s[i-1]<<24)>>>0)),t)}function V(e,t){return B(e.subarray(((8!=(15&(s=e)[0])||s[0]>>4>7||(s[0]<<8|s[1])%31)&&_(6,"invalid zlib data"),1==(s[1]>>5&1)&&_(6,"invalid zlib data: "+(32&s[1]?"need":"unexpected")+" dictionary"),2+(s[1]>>3&4)),-4),{i:2},t,t);var s}var P="undefined"!=typeof TextDecoder&&new TextDecoder;try{P.decode(U,{stream:!0})}catch(e){}class ${constructor(e,t={}){this.debugEnabled=Boolean(t.debug);try{this.bits=this.decompress(e),this.size=8*this.bits.length,this.k=7}catch(t){this.bits=e,this.size=8*this.bits.length,this.k=7}}test(e){if(!this.isValidEan(e))return this.debug("[BloomFilter] Invalid EAN format:",e),!1;this.debug("[BloomFilter] Testing EAN:",e,"Size:",this.size,"Bits length:",this.bits.length);for(let t=0;t<this.k;t++){const s=this.hash(e+t),i=s%this.size,r=Math.floor(i/8),n=i%8,a=!!(this.bits[r]&1<<n);if(this.debug(`[BloomFilter] Hash ${t}: ${s} % ${this.size} = ${i}, byte=${r}, bit=${n}, value=${a}`),!a)return this.debug(`[BloomFilter] EAN ${e} NOT found (hash ${t} failed)`),!1}return this.debug(`[BloomFilter] EAN ${e} FOUND (all ${this.k} hashes passed)`),!0}hash(e){const t=this.getCrc32Table();let s=4294967295;for(let i=0;i<e.length;i++){s=s>>>8^t[255&(s^e.charCodeAt(i))]}return Math.abs((4294967295^s)>>>0)}getCrc32Table(){return this.crc32Table||(this.crc32Table=new Uint32Array([0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117])),this.crc32Table}isValidEan(e){return"string"==typeof e&&/^\d{8}$|^\d{12}$|^\d{13}$/.test(e)}decompress(e){try{let t=e instanceof Uint8Array?e:new Uint8Array(e);if(0===t.length)return t;if(120===t[0]){this.debug("[BloomFilter] Detected zlib/gzcompress data, inflating");try{return V(t)}catch(e){this.debug("[BloomFilter] unzlibSync failed, fallback to raw:",e.message)}}if(31===t[0]&&139===t[1]){this.debug("[BloomFilter] Detected gzip data, inflating");try{return O(t)}catch(e){this.debug("[BloomFilter] gunzipSync failed, fallback to raw:",e.message)}}}catch(e){this.debug("[BloomFilter] Decompression failed:",e.message)}const t=e instanceof Uint8Array?e:new Uint8Array(e);return this.debug("[BloomFilter] Using raw data, size:",t.length),t}getStats(){return{size:this.size,bytes:this.bits.length,hashFunctions:this.k,loaded:!0}}debug(...e){this.debugEnabled}}class x extends a{constructor(e){super(),this.config=e,this.baseUrl=this.config.apiBaseUrl,this.defaultHeaders=this.buildDefaultHeaders(),this.retryConfig={maxRetries:3,baseDelay:1e3,maxDelay:1e4},this.requestQueue=[],this.isProcessingQueue=!1,this.rateLimitInfo={remaining:null,resetTime:null,limit:null},this.bloomFilter=null,this.bloomLoaded=!1,this.bloomLoadPromise=null}buildDefaultHeaders(){const e=this.config.version||"3.0.0-unified",t={"Content-Type":"application/json",Accept:"application/json","User-Agent":`ViprosSDK/${e} (JavaScript)`,"X-SDK-Version":e,"X-SDK-Client":"JavaScript"};return this.config.apiKey&&(t["x-api-key"]=this.config.apiKey),"undefined"!=typeof window&&window.location&&(t.Referer=window.location.href,t.Origin=window.location.origin),t}async getCatalogItems(e={},t={}){this.debug("[ViprosSDK] getCatalogItems() called with filters:",e,"options:",t);const s=new URLSearchParams;Object.entries(e).forEach(([e,t])=>{null!=t&&""!==t&&s.append(e,t.toString())}),t.enableInlineSync&&(s.append("sync","auto"),t.productUrl&&s.append("product_url",t.productUrl),t.forceSync&&s.append("force_sync","1"),s.append("debug","true"));const i=`${this.baseUrl}/sdk/catalog/items${s.toString()?"?"+s.toString():""}`,r={};return t.enableInlineSync&&t.productUrl&&(r["X-Product-Url"]=t.productUrl),this.request("GET",i,null,{headers:r})}async getCatalogItemByEan(e,t={}){this.debug("[ViprosSDK] getCatalogItemByEan() called with ean:",e,"options:",t);if(await this.shouldSkipEan(e))return this.debug("[ViprosSDK] getCatalogItemByEan() - EAN not in bloom filter, skipping API call"),null;const s=new URLSearchParams;t.enableInlineSync&&(s.append("sync","auto"),t.productUrl&&s.append("product_url",t.productUrl),t.forceSync&&s.append("force_sync","1"),s.append("debug","true"));const i=s.toString(),r=`${this.baseUrl}/sdk/catalog/items/${encodeURIComponent(e)}${i?"?"+i:""}`,n={};t.enableInlineSync&&t.productUrl&&(n["X-Product-Url"]=t.productUrl);try{const t=await this.request("GET",r,null,{headers:n});return 404!==t.code&&t.item?(this.debug("[ViprosSDK] getCatalogItemByEan() - Product found:",t.item?.name),t.item):(this.debug("[ViprosSDK] getCatalogItemByEan() - Product not found for EAN:",e),null)}catch(e){return this.debug("[ViprosSDK] getCatalogItemByEan() - Error:",e?.message||e),null}}async updateProductUrls(e){if(!Array.isArray(e)||0===e.length)throw new Error("Updates must be a non-empty array");const t=`${this.baseUrl}/catalog/stores/update_urls`;return this.request("POST",t,{updates:e})}async getProductUpdates(){const e=`${this.baseUrl}/catalog/stores/get_updates`;return this.request("GET",e)}async healthCheck(){const e=`${this.baseUrl}/sdk/health`;return this.request("GET",e)}async syncProduct(e,t,s=!1){if(!e||!t)throw new Error("EAN and product URL are required for synchronization");const i=`${this.config.apiBaseUrl}/partners-stores/sync`,r={ean:e.toString(),url:t};return s&&(r.force_sync=!0),this.request("POST",i,r,{headers:{}})}async get(e,t={},s={}){if("/catalog/items"===e){if(t.ean&&!t.ean.includes(",")){this.debug("[ViprosSDK] get() method - using optimized single EAN route");const e=await this.getCatalogItemByEan(t.ean,s);return e?{items:[e],code:200}:{items:[],code:404,metadata:{ean:t.ean,optimizedRoute:!0}}}if(t.ean){const e=await this.shouldSkipEan(t.ean);if(this.debug(`[ViprosSDK] get() method - shouldSkip: ${e}`),e)return this.debug("[ViprosSDK] get() method - returning empty items, API call skipped (bloom filter)"),{items:[],metadata:{bloomFilter:{skipped:!0,reason:"NOT_IN_FILTER",ean:t.ean}}}}return this.debug("[ViprosSDK] get() method - calling getCatalogItems() with options:",s),this.getCatalogItems(t,s)}const i=`${this.baseUrl}${e}`,r=new URLSearchParams;Object.entries(t).forEach(([e,t])=>{null!=t&&""!==t&&r.append(e,t.toString())});const n=r.toString()?`${i}?${r.toString()}`:i;return this.request("GET",n)}async request(e,t,s=null,i={}){return new Promise((r,n)=>{const a={method:e,url:t,data:s,options:{retry:!0,...i},resolve:r,reject:n,attempts:0};this.requestQueue.push(a),this.processQueue()})}async processQueue(){if(!this.isProcessingQueue&&0!==this.requestQueue.length){for(this.isProcessingQueue=!0;this.requestQueue.length>0;){const e=this.requestQueue.shift();try{const t=await this.executeRequest(e);e.resolve(t)}catch(t){e.options.retry&&this.shouldRetry(t,e)?await this.scheduleRetry(e):e.reject(t)}if(null!==this.rateLimitInfo.remaining&&this.rateLimitInfo.remaining<=1){const e=this.calculateRateLimitDelay();e>0&&await this.sleep(e)}}this.isProcessingQueue=!1}}async executeRequest(e){const{method:t,url:s,data:i,options:r}=e;e.attempts++;const n={method:t,headers:{...this.defaultHeaders,...r.headers},credentials:"omit"};if(!i||"POST"!==t&&"PUT"!==t&&"PATCH"!==t||(n.body=JSON.stringify(i)),r.timeout){const e=new AbortController;n.signal=e.signal,setTimeout(()=>e.abort(),r.timeout)}const a=Date.now();try{const e=await fetch(s,n),i=Date.now()-a;if(this.updateRateLimitInfo(e),!e.ok){const t=await this.handleErrorResponse(e);throw this.emit("error",t),t}const r=await e.json();return this.emit("response",{url:s,method:t,status:e.status,responseTime:i,data:r}),r}catch(e){if("AbortError"===e.name)throw this.createNetworkError("TIMEOUT",`Request timeout after ${r.timeout}ms`,s,t);if("TypeError"===e.name&&e.message.includes("fetch"))throw this.createNetworkError("NETWORK_ERROR","Network error - please check your connection",s,t,e);throw e}}async handleErrorResponse(e){const t=e.headers.get("content-type");let s;try{s=t&&t.includes("application/json")?await e.json():{message:await e.text()}}catch(t){s={message:`HTTP ${e.status}`}}const i=new Error(s.message||`HTTP ${e.status}`);switch(i.status=e.status,i.code=s.code||e.status,i.url=e.url,i.data=s,e.status){case 400:i.type="VALIDATION_ERROR";break;case 401:i.type="AUTHENTICATION_ERROR";break;case 403:i.type="AUTHORIZATION_ERROR";break;case 404:i.type="NOT_FOUND";break;case 429:i.type="RATE_LIMIT_ERROR",i.retryAfter=parseInt(e.headers.get("Retry-After"))||60;break;case 500:i.type="SERVER_ERROR";break;case 502:case 503:case 504:i.type="SERVICE_UNAVAILABLE";break;default:i.type="UNKNOWN_ERROR"}return i}shouldRetry(e,t){if(t.attempts>=this.retryConfig.maxRetries)return!1;if(!t.options.retry)return!1;if(429===e.status||"RATE_LIMIT_ERROR"===e.type)return!1;const s=["SERVER_ERROR","SERVICE_UNAVAILABLE","TIMEOUT","NETWORK_ERROR"];return[500,502,503,504].includes(e.status)||s.includes(e.type)||s.includes(e.code)}async scheduleRetry(e){const t=this.calculateRetryDelay(e);await this.sleep(t),this.requestQueue.unshift(e)}calculateRetryDelay(e){const t=this.retryConfig.baseDelay*Math.pow(2,e.attempts-1),s=1e3*Math.random();return Math.min(t+s,this.retryConfig.maxDelay)}calculateRateLimitDelay(){if(!this.rateLimitInfo.resetTime)return 0;const e=Date.now(),t=1e3*this.rateLimitInfo.resetTime;return Math.max(0,t-e+1e3)}updateRateLimitInfo(e){const t=e.headers.get("X-RateLimit-Limit"),s=e.headers.get("X-RateLimit-Remaining"),i=e.headers.get("X-RateLimit-Reset");t&&(this.rateLimitInfo.limit=parseInt(t)),s&&(this.rateLimitInfo.remaining=parseInt(s)),i&&(this.rateLimitInfo.resetTime=parseInt(i))}sleep(e){return new Promise(t=>setTimeout(t,e))}getRateLimitInfo(){return{...this.rateLimitInfo}}getQueueStatus(){return{queueLength:this.requestQueue.length,isProcessing:this.isProcessingQueue}}clearQueue(){this.requestQueue.forEach(e=>{e.reject(new Error("Request queue cleared"))}),this.requestQueue=[],this.isProcessingQueue=!1}createNetworkError(e,t,s,i,r=null){const n=new Error(t);return n.code=e,n.url=s,n.method=i,r&&(n.originalError=r),n}destroy(){this.clearQueue(),this.removeAllListeners()}async shouldSkipEan(e){try{if(this.debug("[ViprosSDK] Bloom filter check for EAN:",e),await this.loadBloomFilter(),!this.bloomFilter)return this.debug("[ViprosSDK] No bloom filter available, allowing API call"),!1;const t=this.bloomFilter.test(e),s=!t;return this.debug(`[ViprosSDK] Bloom filter test for ${e}: ${t}, shouldSkip: ${s}`),s}catch(e){return this.debug("[ViprosSDK] Bloom filter error:",e?.message||e),!1}}async loadBloomFilter(){return this.bloomLoaded?this.bloomFilter:(this.bloomLoadPromise||(this.bloomLoadPromise=(async()=>{try{const e=this.getStorage();if(e){const t=e.getItem("vipros_bloom"),s=e.getItem("vipros_bloom_time");if(t&&s&&Date.now()-parseInt(s,10)<864e5)return this.bloomFilter=new $(this.base64ToUint8Array(t),{debug:this.isDebugEnabled()}),this.debug("[ViprosSDK] Bloom filter loaded from cache"),this.bloomLoaded=!0,this.bloomFilter}const t=await fetch(`${this.baseUrl}/sdk/bloom`,{headers:{Accept:"application/octet-stream","x-api-key":this.config.apiKey}});if(!t.ok)return this.debug("[ViprosSDK] Unable to download bloom filter, status:",t.status),this.bloomFilter=null,this.bloomLoaded=!0,this.bloomFilter;const s=await t.arrayBuffer(),i=new Uint8Array(s);return this.bloomFilter=new $(i,{debug:this.isDebugEnabled()}),e&&(e.setItem("vipros_bloom",this.uint8ArrayToBase64(i)),e.setItem("vipros_bloom_time",Date.now().toString())),this.debug("[ViprosSDK] Bloom filter downloaded and cached"),this.bloomLoaded=!0,this.bloomFilter}catch(e){return this.debug("[ViprosSDK] Bloom filter unavailable:",e?.message||e),this.bloomFilter=null,this.bloomLoaded=!0,this.bloomFilter}finally{this.bloomLoadPromise=null}})()),this.bloomLoadPromise)}uint8ArrayToBase64(e){if("undefined"!=typeof globalThis&&globalThis.Buffer)return globalThis.Buffer.from(e).toString("base64");let t="";for(let s=0;s<e.length;s+=32768){const i=e.subarray(s,s+32768);let r="";for(let e=0;e<i.length;e++)r+=String.fromCharCode(i[e]);t+=r}return btoa(t)}base64ToUint8Array(e){if("undefined"!=typeof globalThis&&globalThis.Buffer)return new Uint8Array(globalThis.Buffer.from(e,"base64"));const t=atob(e),s=t.length,i=new Uint8Array(s);for(let e=0;e<s;e++)i[e]=t.charCodeAt(e);return i}getStorage(){if("undefined"==typeof window||!window.localStorage)return null;try{const e="__vipros_storage_test__";return window.localStorage.setItem(e,"1"),window.localStorage.removeItem(e),window.localStorage}catch(e){return this.debug("[ViprosSDK] localStorage unavailable:",e?.message||e),null}}debug(...e){this.isDebugEnabled()}isDebugEnabled(){return Boolean(this.config&&this.config.debug)}}var N=Object.freeze({__proto__:null,default:x});class z extends a{constructor(e=3e5){super(),("number"!=typeof e||isNaN(e)||e<0)&&(e=3e5),this.cacheTimeout=e,this.memoryCache=new Map,this.setupCleanupInterval()}get(e,t=!0){const s=this.buildKey(e);let i=this.memoryCache.get(s);return i&&this.isValidCacheEntry(i)?(i.hits=(i.hits||0)+1,i.lastAccessTime=Date.now(),this.emit("hit",{key:e,source:"memory"}),i.data):(this.emit("miss",{key:e}),null)}set(e,t,s={}){const i=this.buildKey(e),r=this.createCacheEntry(t,s);this.memoryCache.set(i,r),this.emit("set",{key:e,size:this.estimateSize(t)}),this.enforceCacheLimits()}createCacheEntry(e,t={}){const s=Date.now(),i=t.ttl||this.cacheTimeout;return{data:e,timestamp:s,expires:i>0?s+i:null,hits:0,lastAccessTime:s,size:this.estimateSize(e),tags:t.tags||[],version:t.version||"3.0.0"}}isValidCacheEntry(e){return!(!e||"object"!=typeof e)&&(!(!e.timestamp||!e.data)&&!(e.expires&&Date.now()>e.expires))}estimateSize(e){try{return JSON.stringify(e).length}catch(e){return 0}}buildKey(e){return`vipros_sdk_${e}`}has(e){const t=this.buildKey(e);if(this.memoryCache.has(t)){const e=this.memoryCache.get(t);return this.isValidCacheEntry(e)}return!1}delete(e){const t=this.buildKey(e),s=this.memoryCache.delete(t);return s&&this.emit("delete",{key:e}),s}clear(){const e=this.memoryCache.size;this.memoryCache.clear(),this.emit("clear",{memorySize:e})}size(){return this.memoryCache.size}getStats(){const e={entries:this.memoryCache.size,totalSize:0,avgSize:0};for(const[,t]of this.memoryCache)e.totalSize+=t.size||0;return e.entries>0&&(e.avgSize=Math.round(e.totalSize/e.entries)),{memory:e}}enforceCacheLimits(){const e=10485760;this.memoryCache.size>100&&this.evictLeastRecentlyUsed(this.memoryCache.size-100);let t=0;for(const[,e]of this.memoryCache)t+=e.size||0;t>e&&this.evictLargestEntries(t-e)}evictLeastRecentlyUsed(e){Array.from(this.memoryCache.entries()).map(([e,t])=>({key:e,lastAccess:t.lastAccessTime||0})).sort((e,t)=>e.lastAccess-t.lastAccess).slice(0,e).forEach(({key:e})=>{this.memoryCache.delete(e)}),this.emit("lru_eviction",{count:e})}evictLargestEntries(e){const t=Array.from(this.memoryCache.entries()).map(([e,t])=>({key:e,entry:t})).sort((e,t)=>(t.entry.size||0)-(e.entry.size||0));let s=0,i=0;for(const{key:r,entry:n}of t){if(s>=e)break;this.memoryCache.delete(r),s+=n.size||0,i++}this.emit("size_eviction",{evicted:i,freedSize:s})}setupCleanupInterval(){"undefined"!=typeof window&&setInterval(()=>{this.cleanupExpiredEntries()},6e4)}cleanupExpiredEntries(){let e=0;const t=Date.now();for(const[s,i]of this.memoryCache)i.expires&&t>i.expires&&(this.memoryCache.delete(s),e++);e>0&&this.emit("cleanup",{cleaned:e})}destroy(){this.clear(),this.removeAllListeners()}}class K extends a{constructor(e,t,s={}){super(),this.apiClient=e,this.cacheService=t,this.config={debug:s.debug||!1,retryDelayMs:5e3,maxRetries:2,...s},this.stats={attempted:0,successful:0,failed:0,skipped:0,rateLimited:0,errors:[]}}syncProductInBackground(e,t){e&&t?this.performSync(e,t).catch(e=>{this.config.debug}):this.config.debug}async performSync(e,t,s=0){this.stats.attempted++;try{const s=await this.apiClient.syncProduct(e,t);if(200===s.code)return this.stats.successful++,this.emit("syncSuccess",{ean:e,productUrl:t,result:s,timestamp:new Date}),this.config.debug,{status:"success",result:s};if(202===s.code)return this.stats.skipped++,this.emit("syncSkipped",{ean:e,reason:"server_cooldown",remaining_hours:s.remaining_hours,next_sync_at:s.next_sync_at}),this.config.debug,{status:"skipped",reason:"server_cooldown"};throw new Error(`API returned status ${s.code}: ${s.message||"Unknown error"}`)}catch(i){return this.handleSyncError(e,t,i,s)}}handleSyncError(e,t,s,i){this.stats.failed++;const r=this.categorizeError(s);return"RATE_LIMIT"===r?(this.stats.rateLimited++,this.emit("syncRateLimited",{ean:e,productUrl:t,error:s,retryAfter:s.retryAfter||60}),this.config.debug,{status:"rate_limited",error:s.message}):"NETWORK_ERROR"===r&&i<this.config.maxRetries?(this.config.debug,setTimeout(()=>{this.performSync(e,t,i+1).catch(()=>{})},this.config.retryDelayMs),{status:"retrying",attempt:i+1}):(this.logError(e,s,r),this.emit("syncError",{ean:e,productUrl:t,error:s,errorType:r,retryCount:i}),this.config.debug,{status:"error",error:s.message,errorType:r})}categorizeError(e){return 429===e.status||"RATE_LIMIT_ERROR"===e.type?"RATE_LIMIT":e.status>=500||"SERVER_ERROR"===e.type?"SERVER_ERROR":"NETWORK_ERROR"===e.code||"NetworkError"===e.name?"NETWORK_ERROR":400===e.status||"VALIDATION_ERROR"===e.type?"VALIDATION_ERROR":"UNKNOWN"}logError(e,t,s){this.stats.errors.push({ean:e,error:t.message,type:s,timestamp:Date.now()}),this.stats.errors.length>100&&(this.stats.errors=this.stats.errors.slice(-50))}getSyncStats(){return{...this.stats,successRate:this.stats.attempted>0?(this.stats.successful/this.stats.attempted*100).toFixed(2)+"%":"0%"}}clearSyncStats(){this.stats={attempted:0,successful:0,failed:0,skipped:0,rateLimited:0,errors:[]}}async forceSyncNow(e,t){return this.performSyncWithForce(e,t)}async performSyncWithForce(e,t){this.stats.attempted++;try{const s=await this.apiClient.syncProduct(e,t,!0);if(200===s.code)return this.stats.successful++,this.emit("syncSuccess",{ean:e,productUrl:t,result:s,forced:!0,timestamp:new Date}),{status:"success",result:s,forced:!0};throw new Error(`API returned status ${s.code}: ${s.message||"Unknown error"}`)}catch(s){return this.stats.failed++,this.logError(e,s,"forced_sync"),this.emit("syncError",{ean:e,productUrl:t,error:s,forced:!0}),{status:"error",error:s.message,forced:!0}}}destroy(){this.clearSyncStats(),this.removeAllListeners()}}class ViprosSDK extends a{constructor(){if(super(),this.version="3.0.0-unified",this.isInitialized=!1,this.config={apiKey:null,debug:!1,syncEnabled:!0,inlineSyncEnabled:!0,disableBackgroundSync:!0,containerSelector:"[data-ean]",autoScan:!0},this._apiClient=null,this._cacheService=null,this._syncService=null,this._servicesInitialized=!1,this.stats={version:this.version,componentsRegistered:0,componentsActive:0,offersLoaded:0,errors:0,cacheHits:0,apiCalls:0,syncAttempts:0,syncSuccess:0},this.cache=new Map,this.eventListeners=new Map,ViprosSDK.instance)return ViprosSDK.instance;ViprosSDK.instance=this}static getInstance(){return ViprosSDK.instance||(ViprosSDK.instance=new ViprosSDK),ViprosSDK.instance}init(e={}){return this.isInitialized?(this.debugLog("SDK déjà initialisé"),this):(this.config=n.create({...this.config,...e}),this.debugLog(`Initialisation VIPros SDK v${this.version}`),this.debugLog("Configuration:",this.config),this.registerWebComponents(),this.config.autoScan&&this.scanAndConvert(),this.isInitialized=!0,this.emitEvent("sdk-ready",{version:this.version,config:this.config}),this.debugLog("SDK initialisé avec lazy loading - services créés à la demande"),this)}get apiClient(){return this._apiClient||(this.debugLog("Création lazy d'ApiClient"),this._apiClient=new x(this.config)),this._apiClient}get cacheService(){return this._cacheService||(this.debugLog("Création lazy de CacheService"),this._cacheService=new z(this.config.cacheTimeout||3e5)),this._cacheService}get syncService(){return!this._syncService&&this.config.syncEnabled&&(this.debugLog("Création lazy d'EanSyncService"),this._syncService=new K(this.apiClient,this.cacheService,this.config),this.setupSyncEvents()),this._syncService}initializeServicesEager(){this.debugLog("Initialisation eager de tous les services...");const e=this.apiClient,t=this.cacheService,s=this.syncService;return this._servicesInitialized=!0,this.debugLog("Tous les services initialisés (eager)"),{api:e,cache:t,sync:s}}setupSyncEvents(){this.syncService&&(this.syncService.on("syncSuccess",e=>{this.stats.syncSuccess++,this.emit("syncSuccess",e)}),this.syncService.on("syncSkipped",e=>{this.emit("syncSkipped",e)}),this.syncService.on("syncError",e=>{this.emit("syncError",e)}),this.syncService.on("syncRateLimited",e=>{this.emit("syncRateLimited",e)}),this.debugLog("Événements de synchronisation connectés"))}getCacheService(){return this.cacheService}syncProductInBackground(e,t){this.config.disableBackgroundSync?this.debugLog("Sync en arrière-plan désactivée (disableBackgroundSync=true)"):this.syncService?(this.stats.syncAttempts++,this.debugLog(`Déclenchement sync pour EAN ${e}`),this.syncService.syncProductInBackground(e,t)):this.debugLog("Sync demandée mais service non disponible")}registerWebComponents(){customElements.get("vipros-offer-card")||(r.setSDKInstance(this),customElements.define("vipros-offer-card",r),this.stats.componentsRegistered++,this.debugLog("vipros-offer-card registered"))}scanAndConvert(){const e=document.querySelectorAll(this.config.containerSelector);this.debugLog(`Scan: ${e.length} containers data-ean trouvés`),e.forEach(e=>{const t=e.getAttribute("data-ean"),s=e.getAttribute("data-price");if(t){const i=document.createElement("vipros-offer-card");i.setAttribute("ean",t),s&&i.setAttribute("price",s),e.parentNode.replaceChild(i,e),this.debugLog(`Converti data-ean="${t}" vers Web Component`)}})}getApiClient(){return this.apiClient}getServicesStatus(){return{apiClientInitialized:!!this._apiClient,cacheServiceInitialized:!!this._cacheService,syncServiceInitialized:!!this._syncService,allServicesEager:this._servicesInitialized}}async getProductData(e){const t=`product_${e}`;if(this.cache.has(t)){const s=this.cache.get(t);if(Date.now()-s.timestamp<this.config.cacheTimeout)return this.stats.cacheHits++,this.debugLog(`Cache hit for EAN ${e}`),s.data}try{this.stats.apiCalls++;const s=await this.apiClient.getCatalogItemByEan(e),i=s?{code:200,item:s}:{code:404,item:null};return s&&this.cache.set(t,{data:i,timestamp:Date.now()}),this.debugLog(`API data loaded for EAN ${e}`),i}catch(t){throw this.stats.errors++,this.debugLog(`Erreur API pour EAN ${e}:`,t),t}}emitEvent(e,t={}){const s=`vipros-${e}`,i=new CustomEvent(s,{detail:t,bubbles:!0,cancelable:!0});document.dispatchEvent(i),this.debugLog(`Event: ${s}`,t)}on(e,t){const s=`vipros-${e}`;document.addEventListener(s,t),this.eventListeners.has(s)||this.eventListeners.set(s,[]),this.eventListeners.get(s).push(t)}off(e,t){const s=`vipros-${e}`;if(document.removeEventListener(s,t),this.eventListeners.has(s)){const e=this.eventListeners.get(s),i=e.indexOf(t);i>-1&&e.splice(i,1)}}clearCache(){this.cache.clear(),this.debugLog("Cache vidé")}refreshAll(){const e=document.querySelectorAll("vipros-offer-card");e.forEach(e=>{e.refresh&&"function"==typeof e.refresh&&e.refresh()}),this.debugLog(`Refresh de ${e.length} composants`)}getStats(){return this.stats.componentsActive=document.querySelectorAll("vipros-offer-card").length,{...this.stats}}debugLog(e,t=null){this.config.debug}destroy(){this.eventListeners.forEach((e,t)=>{e.forEach(e=>{document.removeEventListener(t,e)})}),this.eventListeners.clear(),this.cache.clear(),this._apiClient&&(this.debugLog("Nettoyage ApiClient"),this._apiClient=null),this._cacheService&&(this.debugLog("Nettoyage CacheService"),this._cacheService=null),this._syncService&&(this.debugLog("Nettoyage SyncService"),this._syncService=null),this._servicesInitialized=!1,this.isInitialized=!1,this.debugLog("SDK détruit")}}const F=new ViprosSDK;return"undefined"!=typeof window&&(window.ViprosSDK=F),F}();"undefined"!=typeof window&&void 0!==ViprosSDKBundle&&(window.ViprosSDK=ViprosSDKBundle);