@vipros-org/sdk 3.0.3 → 3.0.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vipros-org/sdk",
3
- "version": "3.0.3",
3
+ "version": "3.0.4",
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",
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-11T13:45:30.171Z
4
+ * Generated: 2026-03-02T13:01:45.763Z
5
5
  */
6
6
 
7
7
  /* VIPros SDK Base Styles */
package/vipros-sdk.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
- * VIPros SDK v3.0.0-unified - Production Build
3
- * Generated: 2026-02-11T13:45:27.756Z
2
+ * VIPros SDK v3.0.4 - Production Build
3
+ * Generated: 2026-03-02T13:01:43.298Z
4
4
  * Environment: Production
5
5
  */
6
6
  var ViprosSDK = (function () {
@@ -476,8 +476,16 @@ var ViprosSDK = (function () {
476
476
  * URL par défaut de l'image VIPoints
477
477
  */
478
478
  static getDefaultVIPointsImageUrl() {
479
- // Sera définie dynamiquement par le composant selon son contexte
480
- return '/api/sdk/assets/image-vipoints.jpg'
479
+ // Construire une URL absolue pour fonctionner sur les sites marchands externes
480
+ try {
481
+ if (typeof window !== 'undefined' && window.ViprosSDK?.config?.apiBaseUrl) {
482
+ const baseUrl = window.ViprosSDK.config.apiBaseUrl.replace(/\/api$/, '');
483
+ return `${baseUrl}/api/sdk/assets/image-vipoints.jpg`
484
+ }
485
+ } catch (e) {
486
+ // Fallback silencieux
487
+ }
488
+ return 'https://api.vipros.fr/api/sdk/assets/image-vipoints.jpg'
481
489
  }
482
490
  }
483
491
 
@@ -946,14 +954,14 @@ var ViprosSDK = (function () {
946
954
  // Edge case: No window object (SSR or Node.js environment)
947
955
  if (typeof window === 'undefined') {
948
956
  this.log('[ViprosOfferCard] No window object - defaulting to production API');
949
- return 'https://msys.vipros.fr/api'
957
+ return 'https://api.vipros.fr/api'
950
958
  }
951
959
 
952
960
  try {
953
961
  // Edge case: window.location is not available or corrupted
954
962
  if (!window.location || typeof window.location.hostname !== 'string') {
955
963
  this.log('[ViprosOfferCard] Invalid window.location - defaulting to production API');
956
- return 'https://msys.vipros.fr/api'
964
+ return 'https://api.vipros.fr/api'
957
965
  }
958
966
 
959
967
  const protocol = window.location.protocol || 'https:';
@@ -962,7 +970,7 @@ var ViprosSDK = (function () {
962
970
  // Edge case: Empty or invalid hostname
963
971
  if (!hostname || hostname.length === 0) {
964
972
  this.log('[ViprosOfferCard] Empty hostname - defaulting to production API');
965
- return 'https://msys.vipros.fr/api'
973
+ return 'https://api.vipros.fr/api'
966
974
  }
967
975
 
968
976
  // Edge case: Local development or non-standard protocols
@@ -976,8 +984,8 @@ var ViprosSDK = (function () {
976
984
  return `${protocol}//${hostname}/api`
977
985
  }
978
986
 
979
- if (hostname === 'msys.preprod.vipros.fr') {
980
- return `${protocol}//msys.preprod.vipros.fr/api`
987
+ if (hostname === 'preprod.api.vipros.fr') {
988
+ return `${protocol}//preprod.api.vipros.fr/api`
981
989
  }
982
990
 
983
991
  // Edge case: Subdomain detection for enterprise customers
@@ -988,12 +996,12 @@ var ViprosSDK = (function () {
988
996
 
989
997
  // Par défaut : production (toujours HTTPS pour la sécurité)
990
998
  this.log(`[ViprosOfferCard] Unknown domain: ${hostname} - defaulting to production API`);
991
- return 'https://msys.vipros.fr/api'
999
+ return 'https://api.vipros.fr/api'
992
1000
 
993
1001
  } catch (error) {
994
1002
  // Edge case: Exception during detection
995
1003
  this.log(`[ViprosOfferCard] Error detecting API base URL: ${error.message} - defaulting to production`);
996
- return 'https://msys.vipros.fr/api'
1004
+ return 'https://api.vipros.fr/api'
997
1005
  }
998
1006
  }
999
1007
 
@@ -1246,6 +1254,8 @@ var ViprosSDK = (function () {
1246
1254
  // Transformer les données
1247
1255
  const productData = ProductDataTransformer.transform(response.items[0], this.price);
1248
1256
  productData.vipointsImageUrl = this.getVIPointsImageUrl();
1257
+ productData.fallbackImageUrl = this.getVIPointsImageUrl();
1258
+ productData.cashbackDefaultImageUrl = this.getAssetUrl('image-cashback.jpg');
1249
1259
 
1250
1260
  this.setProductData(productData);
1251
1261
  this.log(`[ViprosOfferCard] Product loaded: ${productData.name}`);
@@ -1373,9 +1383,13 @@ var ViprosSDK = (function () {
1373
1383
  }
1374
1384
 
1375
1385
  // Utilitaires
1386
+ getAssetUrl(filename) {
1387
+ const baseUrl = (this.apiBaseUrl || '').replace(/\/api$/, '');
1388
+ return `${baseUrl}/api/sdk/assets/${filename}`
1389
+ }
1390
+
1376
1391
  getVIPointsImageUrl() {
1377
- const baseUrl = (this.apiBaseUrl || '').replace('/api', '');
1378
- return `${baseUrl}/api/sdk/assets/image-vipoints.jpg`
1392
+ return this.getAssetUrl('image-vipoints.jpg')
1379
1393
  }
1380
1394
 
1381
1395
  triggerBackgroundSync() {
@@ -1503,7 +1517,7 @@ var ViprosSDK = (function () {
1503
1517
  dateFormat: 'DD/MM/YYYY',
1504
1518
 
1505
1519
  // Version
1506
- version: '1.0.0'
1520
+ version: "3.0.4"
1507
1521
  }
1508
1522
  }
1509
1523
 
@@ -1725,13 +1739,13 @@ var ViprosSDK = (function () {
1725
1739
  // Edge case: No window object (SSR, Node.js, service worker)
1726
1740
  if (typeof window === 'undefined') {
1727
1741
  if (debug) console.warn('[ConfigManager] No window object - defaulting to production API');
1728
- return 'https://msys.vipros.fr/api'
1742
+ return 'https://api.vipros.fr/api'
1729
1743
  }
1730
1744
 
1731
1745
  // Edge case: window.location is not available or corrupted
1732
1746
  if (!window.location || typeof window.location.hostname !== 'string') {
1733
1747
  if (debug) console.warn('[ConfigManager] Invalid window.location - defaulting to production API');
1734
- return 'https://msys.vipros.fr/api'
1748
+ return 'https://api.vipros.fr/api'
1735
1749
  }
1736
1750
 
1737
1751
  const protocol = window.location.protocol || 'https:';
@@ -1740,7 +1754,7 @@ var ViprosSDK = (function () {
1740
1754
  // Edge case: Empty or invalid hostname
1741
1755
  if (!hostname || hostname.length === 0) {
1742
1756
  if (debug) console.warn('[ConfigManager] Empty hostname - defaulting to production API');
1743
- return 'https://msys.vipros.fr/api'
1757
+ return 'https://api.vipros.fr/api'
1744
1758
  }
1745
1759
 
1746
1760
  // Edge case: Local development environments
@@ -1760,8 +1774,8 @@ var ViprosSDK = (function () {
1760
1774
  return `${protocol}//${hostname}/api`
1761
1775
  }
1762
1776
 
1763
- if (hostname === 'msys.preprod.vipros.fr') {
1764
- return `${protocol}//msys.preprod.vipros.fr/api`
1777
+ if (hostname === 'preprod.api.vipros.fr') {
1778
+ return `${protocol}//preprod.api.vipros.fr/api`
1765
1779
  }
1766
1780
 
1767
1781
  // Edge case: Enterprise subdomains or custom VIPros domains
@@ -1773,17 +1787,17 @@ var ViprosSDK = (function () {
1773
1787
  // Edge case: IP addresses (development/staging environments)
1774
1788
  if (/^\d+\.\d+\.\d+\.\d+$/.test(hostname)) {
1775
1789
  if (debug) console.log(`[ConfigManager] IP address detected: ${hostname} - using production API`);
1776
- return 'https://msys.vipros.fr/api'
1790
+ return 'https://api.vipros.fr/api'
1777
1791
  }
1778
1792
 
1779
1793
  // Par défaut : production (toujours HTTPS pour la sécurité)
1780
1794
  if (debug) console.log(`[ConfigManager] Unknown domain: ${hostname} - defaulting to production API`);
1781
- return 'https://msys.vipros.fr/api'
1795
+ return 'https://api.vipros.fr/api'
1782
1796
 
1783
1797
  } catch (error) {
1784
1798
  // Edge case: Unexpected error during detection
1785
1799
  if (debug) console.error(`[ConfigManager] Error during API base URL detection: ${error.message} - defaulting to production`);
1786
- return 'https://msys.vipros.fr/api'
1800
+ return 'https://api.vipros.fr/api'
1787
1801
  }
1788
1802
  }
1789
1803
  }
@@ -2536,7 +2550,7 @@ var ViprosSDK = (function () {
2536
2550
  }
2537
2551
 
2538
2552
  buildDefaultHeaders () {
2539
- const sdkVersion = this.config.version || '3.0.0-unified';
2553
+ const sdkVersion = this.config.version || "3.0.4";
2540
2554
  const headers = {
2541
2555
  'Content-Type': 'application/json',
2542
2556
  'Accept': 'application/json',
@@ -3737,7 +3751,7 @@ var ViprosSDK = (function () {
3737
3751
  class ViprosSDK extends EventEmitter {
3738
3752
  constructor() {
3739
3753
  super();
3740
- this.version = '3.0.0-unified';
3754
+ this.version = "3.0.4";
3741
3755
  this.isInitialized = false;
3742
3756
 
3743
3757
  // Configuration par défaut non validée - sera validée au moment de init()
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * VIPros SDK - CSS File
3
3
  * Version: 3.0.0-unified
4
- * Generated: 2026-02-11T13:45:30.171Z
4
+ * Generated: 2026-03-02T13:01:45.763Z
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-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);
1
+ /*! VIPros SDK v3.0.4 - Production Minified - 2026-03-02T13:01:43.298Z */
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()),a=Boolean(r),n=i.split(/\{\{else\}\}/);return 2===n.length?a?n[0]:n[1]:a?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),a=Boolean(r);return(s?a:!a)?"":"\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(){try{if("undefined"!=typeof window&&window.ViprosSDK?.config?.apiBaseUrl){return`${window.ViprosSDK.config.apiBaseUrl.replace(/\/api$/,"")}/api/sdk/assets/image-vipoints.jpg`}}catch(e){}return"https://api.vipros.fr/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 a=this.resolveDisplayMode(e),n=this.resolveTemplateName(a),o=this.shouldDisplay(a),c=this.resolveContainerClass(a);return{mode:this.validateDisplayMode(a),template:n,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://api.vipros.fr/api";try{if(!window.location||"string"!=typeof window.location.hostname)return this.log("[ViprosOfferCard] Invalid window.location - defaulting to production API"),"https://api.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`:"preprod.api.vipros.fr"===t?`${e}//preprod.api.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://api.vipros.fr/api"):(this.log("[ViprosOfferCard] Empty hostname - defaulting to production API"),"https://api.vipros.fr/api")}catch(e){return this.log(`[ViprosOfferCard] Error detecting API base URL: ${e.message} - defaulting to production`),"https://api.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,a=Boolean(this.getConfigValue("debug")||"true"===this.getAttribute("debug"));if(r?.skipped){if(this.log(`[ViprosOfferCard] Bloom filter skipped API call for EAN ${this.ean}`),a){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 n=i?.sdk_metadata?.sync;if(n&&this.getConfigValue("debug")&&this.log("[ViprosOfferCard] Sync metadata:",n),i.items&&i.items.length>0){const e=t.transform(i.items[0],this.price);e.vipointsImageUrl=this.getVIPointsImageUrl(),e.fallbackImageUrl=this.getVIPointsImageUrl(),e.cashbackDefaultImageUrl=this.getAssetUrl("image-cashback.jpg"),this.setProductData(e),this.log(`[ViprosOfferCard] Product loaded: ${e.name}`);null!=n?this.log(`[ViprosOfferCard] Skipping background sync (inline sync was attempted, status: ${n.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)}getAssetUrl(e){return`${(this.apiBaseUrl||"").replace(/\/api$/,"")}/api/sdk/assets/${e}`}getVIPointsImageUrl(){return this.getAssetUrl("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 a{static create(e={}){const t=a.getDefaultConfig(),s=a.mergeConfig(t,e);return a.validateConfig(s)}static getDefaultConfig(){return{apiBaseUrl:a.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:"3.0.4"}}static mergeConfig(e,t){return a.deepMerge(e,t)}static deepMerge(e,t){const s={...e};for(const[e,i]of Object.entries(t))null!=i&&(a.isObject(i)&&a.isObject(s[e])?s[e]=a.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&&!a.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 a.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 a.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://api.vipros.fr/api";if(!window.location||"string"!=typeof window.location.hostname)return"https://api.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`:"preprod.api.vipros.fr"===t?`${e}//preprod.api.vipros.fr/api`:t.endsWith(".vipros.fr")?`${e}//${t}/api`:(/^\d+\.\d+\.\d+\.\d+$/.test(t),"https://api.vipros.fr/api"):"https://api.vipros.fr/api"}catch(e){return"https://api.vipros.fr/api"}}}class n{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 a=s[i];a<s[i+1];++a)r[a]=a-s[i]<<5|i;return{b:s,r:r}},g=p(h,2),m=g.b,f=g.r;m[28]=258,f[258]=28;for(var y=p(u,0).b,b=new c(32768),v=0;v<32768;++v){var w=(43690&v)>>1|(21845&v)<<1;w=(61680&(w=(52428&w)>>2|(13107&w)<<2))>>4|(3855&w)<<4,b[v]=((65280&w)>>8|(255&w)<<8)>>1}var C=function(e,t,s){for(var i=e.length,r=0,a=new c(t);r<i;++r)e[r]&&++a[e[r]-1];var n,o=new c(t);for(r=1;r<t;++r)o[r]=o[r-1]+a[r-1]<<1;if(s){n=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)n[b[d]>>l]=h}else for(n=new c(i),r=0;r<i;++r)e[r]&&(n[r]=b[o[e[r]-1]++]>>15-e[r]);return n},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=C(S,9,1),L=C(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},I=function(e,t,s){var i=t/8|0;return(e[i]|e[i+1]<<8)>>(7&t)&s},A=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"],U=function(e,t,s){var i=new Error(t||T[e]);if(i.code=e,Error.captureStackTrace&&Error.captureStackTrace(i,U),!s)throw i;return i},_=function(e,t,s,i){var r=e.length;if(!r||t.f&&!t.l)return s||new o(0);var a=!s,n=a||2!=t.i,c=t.i;a&&(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,g=t.p||0,f=t.b||0,b=t.l,v=t.d,w=t.m,S=t.n,E=8*r;do{if(!b){p=I(e,g,1);var T=I(e,g+1,3);if(g+=3,!T){var _=e[(M=D(g)+4)-4]|e[M-3]<<8,B=M+_;if(B>r){c&&U(0);break}n&&l(f+_),s.set(e.subarray(M,B),f),t.b=f+=_,t.p=g=8*B,t.f=p;continue}if(1==T)b=k,v=L,w=9,S=5;else if(2==T){var O=I(e,g,31)+257,V=I(e,g+10,15)+4,$=O+I(e,g+5,31)+1;g+=14;for(var P=new o($),x=new o(19),N=0;N<V;++N)x[d[N]]=I(e,g+3*N,7);g+=3*V;var z=R(x),K=(1<<z)-1,F=C(x,z,1);for(N=0;N<$;){var M,q=F[I(e,g,K)];if(g+=15&q,(M=q>>4)<16)P[N++]=M;else{var j=0,W=0;for(16==M?(W=3+I(e,g,3),g+=2,j=P[N-1]):17==M?(W=3+I(e,g,7),g+=3):18==M&&(W=11+I(e,g,127),g+=7);W--;)P[N++]=j}}var Q=P.subarray(0,O),H=P.subarray(O);w=R(Q),S=R(H),b=C(Q,w,1),v=C(H,S,1)}else U(1);if(g>E){c&&U(0);break}}n&&l(f+131072);for(var G=(1<<w)-1,X=(1<<S)-1,J=g;;J=g){var Y=(j=b[A(e,g)&G])>>4;if((g+=15&j)>E){c&&U(0);break}if(j||U(2),Y<256)s[f++]=Y;else{if(256==Y){J=g,b=null;break}var Z=Y-254;if(Y>264){var ee=h[N=Y-257];Z=I(e,g,(1<<ee)-1)+m[N],g+=ee}var te=v[A(e,g)&X],se=te>>4;te||U(3),g+=15&te;H=y[se];if(se>3){ee=u[se];H+=A(e,g)&(1<<ee)-1,g+=ee}if(g>E){c&&U(0);break}n&&l(f+131072);var ie=f+Z;if(f<H){var re=0-H,ae=Math.min(H,ie);for(re+f<0&&U(3);f<ae;++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=w,t.d=v,t.n=S)}while(!p);return f!=s.length&&a?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)},B=new o(0);function O(e,t){var s,i,r=function(e){31==e[0]&&139==e[1]&&8==e[2]||U(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&&U(6,"invalid gzip data"),_(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 _(e.subarray(((8!=(15&(s=e)[0])||s[0]>>4>7||(s[0]<<8|s[1])%31)&&U(6,"invalid zlib data"),1==(s[1]>>5&1)&&U(6,"invalid zlib data: "+(32&s[1]?"need":"unexpected")+" dictionary"),2+(s[1]>>3&4)),-4),{i:2},t,t);var s}var $="undefined"!=typeof TextDecoder&&new TextDecoder;try{$.decode(B,{stream:!0})}catch(e){}class P{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),a=i%8,n=!!(this.bits[r]&1<<a);if(this.debug(`[BloomFilter] Hash ${t}: ${s} % ${this.size} = ${i}, byte=${r}, bit=${a}, value=${n}`),!n)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 n{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.4",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:""}`,a={};t.enableInlineSync&&t.productUrl&&(a["X-Product-Url"]=t.productUrl);try{const t=await this.request("GET",r,null,{headers:a});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 a=r.toString()?`${i}?${r.toString()}`:i;return this.request("GET",a)}async request(e,t,s=null,i={}){return new Promise((r,a)=>{const n={method:e,url:t,data:s,options:{retry:!0,...i},resolve:r,reject:a,attempts:0};this.requestQueue.push(n),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 a={method:t,headers:{...this.defaultHeaders,...r.headers},credentials:"omit"};if(!i||"POST"!==t&&"PUT"!==t&&"PATCH"!==t||(a.body=JSON.stringify(i)),r.timeout){const e=new AbortController;a.signal=e.signal,setTimeout(()=>e.abort(),r.timeout)}const n=Date.now();try{const e=await fetch(s,a),i=Date.now()-n;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 a=new Error(t);return a.code=e,a.url=s,a.method=i,r&&(a.originalError=r),a}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 P(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 P(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 n{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:a}of t){if(s>=e)break;this.memoryCache.delete(r),s+=a.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 n{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 n{constructor(){if(super(),this.version="3.0.4",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=a.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);