class VehicleDashboard{constructor(){this.currentView="brands",this.selectedBrand=null,this.selectedModel=null,this.selectedYear=null,this.selectedVehicleId=null,this.selectedCategory=null,this.selectedGroupId=null,this.selectedGroup=null,this.allVehicles=[],this.filteredVehicles=[],this.allCategories=[],this.allParts=[],this.stats={brands:0,models:0,vehicles:0,parts:0},this.currentDiagramZoom=1,this.lastFocusedElement=null,this.init()}async init(){await this.loadStats(),await this.showBrands(),this.bindFilterEvents(),this.bindKeyboardShortcuts(),this.bindSearchEvents(),this.initDarkMode()}bindSearchEvents(){const e=document.getElementById("searchInput");e&&e.addEventListener("keypress",(e=>{"Enter"===e.key&&this.searchPartNumber()}))}async loadStats(){try{const[e,t,a]=await Promise.all([fetch("/api/catalog/stats"),fetch("/api/brands"),fetch("/api/categories")]);if(e.ok){const t=await e.json();this.stats.brands=t.brands,this.stats.models=t.models,this.stats.vehicles=t.vehicles,this.stats.parts=t.parts;const a=e=>e>1e3?Math.floor(e/1e3)+"K+":e,s=document.getElementById("totalBrands"),n=document.getElementById("totalModels"),i=document.getElementById("totalParts");s&&(s.textContent=a(this.stats.brands)),n&&(n.textContent=a(this.stats.models)),i&&(i.textContent=a(this.stats.parts))}t.ok&&await t.json(),a.ok&&(this.allCategories=await a.json())}catch(e){console.error("Error loading stats:",e)}}updateBreadcrumb(){const e=document.getElementById("breadcrumb");let t=[];if("brands"===this.currentView)t.push({label:' Marcas',active:!0});else if("models"===this.currentView)t.push({label:' Marcas',action:"dashboard.goToBrands()"}),t.push({label:this.selectedBrand,active:!0});else if("vehicles"===this.currentView)t.push({label:' Marcas',action:"dashboard.goToBrands()"}),t.push({label:this.selectedBrand,action:`dashboard.goToModels('${this.selectedBrand.replace(/'/g,"\\'")}')`}),t.push({label:this.selectedModel,active:!0});else if("categories"===this.currentView)t.push({label:' Marcas',action:"dashboard.goToBrands()"}),t.push({label:this.selectedBrand,action:`dashboard.goToModels('${this.selectedBrand.replace(/'/g,"\\'")}')`}),t.push({label:this.selectedModel,action:`dashboard.goToVehicles('${this.selectedBrand.replace(/'/g,"\\'")}', '${this.selectedModel.replace(/'/g,"\\'")}')`}),this.selectedYear&&t.push({label:this.selectedYear}),t.push({label:"Categorías",active:!0});else if("groups"===this.currentView)t.push({label:' Marcas',action:"dashboard.goToBrands()"}),t.push({label:this.selectedBrand,action:`dashboard.goToModels('${this.selectedBrand.replace(/'/g,"\\'")}')`}),t.push({label:this.selectedModel,action:`dashboard.goToVehicles('${this.selectedBrand.replace(/'/g,"\\'")}', '${this.selectedModel.replace(/'/g,"\\'")}')`}),this.selectedYear&&t.push({label:this.selectedYear}),t.push({label:"Categorías",action:`dashboard.goToCategories(${this.selectedVehicleId})`}),t.push({label:this.selectedCategory?this.selectedCategory.name_es||this.selectedCategory.name:"Grupos",active:!0});else if("parts"===this.currentView){const e=this.selectedGroup?this.selectedGroup.name_es||this.selectedGroup.name:"Grupo";t.push({label:' Marcas',action:"dashboard.goToBrands()"}),t.push({label:this.selectedBrand,action:`dashboard.goToModels('${this.selectedBrand.replace(/'/g,"\\'")}')`}),t.push({label:this.selectedModel,action:`dashboard.goToVehicles('${this.selectedBrand.replace(/'/g,"\\'")}', '${this.selectedModel.replace(/'/g,"\\'")}')`}),this.selectedYear&&t.push({label:this.selectedYear}),t.push({label:"Categorías",action:`dashboard.goToCategories(${this.selectedVehicleId})`}),t.push({label:this.selectedCategory?this.selectedCategory.name_es||this.selectedCategory.name:"Categoría",action:`dashboard.goToGroups(${this.selectedCategory?this.selectedCategory.id:0})`}),t.push({label:e,active:!0})}e.innerHTML=t.map(((e,a)=>{const s=a===t.length-1?"":'/ ';return e.action?`${e.label} ${s}`:e.active?`${e.label} `:`${e.label} ${s}`})).join("")}bindKeyboardShortcuts(){document.addEventListener("keydown",(e=>{const t="INPUT"===e.target.tagName||"TEXTAREA"===e.target.tagName;if("Escape"!==e.key){if(!t){if(!("/"===e.key||e.ctrlKey&&"k"===e.key))return e.ctrlKey&&"d"===e.key?(e.preventDefault(),void this.toggleDarkMode()):"Backspace"===e.key?(e.preventDefault(),void this.goBack()):void 0;{e.preventDefault();const t=document.getElementById("searchInput");t&&t.focus()}}}else this.closeAllModals()}))}closeAllModals(){["partDetailModal","searchResultsModal","diagramModal","vinDecoderModal"].forEach((e=>{this.closeModal(e)}))}openModal(e){this.lastFocusedElement=document.activeElement;const t=document.getElementById(e);t&&(t.classList.add("active"),setTimeout((()=>{const e=t.querySelector('input, button, [tabindex]:not([tabindex="-1"])');e&&e.focus()}),100))}closeModal(e){const t=document.getElementById(e);t&&(t.classList.remove("active"),this.lastFocusedElement&&this.lastFocusedElement.focus())}goBack(){switch(this.currentView){case"models":this.goToBrands();break;case"vehicles":this.goToModels(this.selectedBrand);break;case"categories":this.goToVehicles(this.selectedBrand,this.selectedModel);break;case"groups":this.goToCategories(this.selectedVehicleId);break;case"parts":this.selectedCategory?this.goToGroups(this.selectedCategory.id):this.goToCategories(this.selectedVehicleId)}}initDarkMode(){}toggleDarkMode(){}updateDarkModeIcon(){}makeCardsAccessible(e,t){const a=document.querySelector(e);if(!a)return;a.querySelectorAll(t).forEach(((e,t)=>{e.setAttribute("tabindex","0"),e.setAttribute("role","button");const a=e.textContent.trim().replace(/\s+/g," ");e.setAttribute("aria-label",a.substring(0,100)),e.addEventListener("keydown",(t=>{"Enter"!==t.key&&" "!==t.key||(t.preventDefault(),e.click())}))}))}openModalWithFocus(e){return this.openModal(e),{hide:()=>this.closeModal(e)}}async showBrands(){this.currentView="brands",this.selectedBrand=null,this.selectedModel=null,this.selectedYear=null,this.selectedGroup=null,this.updateBreadcrumb(),this.hideFilters();const e=document.getElementById("mainContent");e.innerHTML='\n
\n \n
Cargando marcas... \n \n ';try{const t=await fetch("/api/brands?detailed=true");if(!t.ok)throw new Error("Error al cargar datos");const a=await t.json(),s={};if(a.forEach((e=>{s[e.name]={models:{size:e.model_count},vehicles:e.vehicle_count}})),0===a.length)return void(e.innerHTML='\n \n
\n
No hay marcas disponibles \n
Agrega algunas marcas a la base de datos
\n
\n ');e.innerHTML=`\n ${a.map((e=>`\n
\n
\n \n
\n
${e.name}
\n
\n ${e.model_count} modelos\n
\n
\n ${e.vehicle_count} vehículos\n
\n
\n `)).join("")}\n
`,this.makeCardsAccessible("#mainContent",".brand-card")}catch(t){console.error("Error:",t),e.innerHTML=`\n \n
\n
Error al cargar marcas \n
${t.message}
\n
\n `}}async goToModels(e){this.currentView="models",this.selectedBrand=e,this.selectedModel=null,this.selectedYear=null,this.selectedGroup=null,this.updateBreadcrumb(),this.hideFilters();const t=document.getElementById("mainContent");t.innerHTML=`\n \n \n
Cargando modelos de ${e}... \n \n `;try{const a=await fetch(`/api/models?brand=${encodeURIComponent(e)}&detailed=true`);if(!a.ok)throw new Error("Error al cargar datos");const s=await a.json();if(0===s.length)return void(t.innerHTML=`\n \n
\n
No hay modelos para ${e} \n
Esta marca no tiene modelos registrados
\n
\n Volver a marcas\n \n
\n `);t.innerHTML=`\n ${s.map((t=>{const a=t.year_count>1?`${t.year_min} - ${t.year_max}`:`${t.year_min}`;return`\n
\n
${t.name}
\n
\n ${a}\n
\n
\n ${t.engine_count} motores\n
\n
\n ${t.vehicle_count} variantes\n
\n
\n `})).join("")}\n
`,this.makeCardsAccessible("#mainContent",".model-card")}catch(e){console.error("Error:",e),t.innerHTML=`\n \n
\n
Error al cargar modelos \n
${e.message}
\n
\n Volver a marcas\n \n
\n `}}async goToVehicles(e,t){this.currentView="vehicles",this.selectedBrand=e,this.selectedModel=t,this.selectedYear=null,this.selectedGroup=null,this.updateBreadcrumb(),this.showFilters();const a=document.getElementById("mainContent");a.innerHTML='\n \n \n
Cargando vehículos... \n \n ';try{const[a,s]=await Promise.all([fetch(`/api/vehicles?brand=${encodeURIComponent(e)}&model=${encodeURIComponent(t)}&per_page=100`),fetch(`/api/model-year-engine?brand=${encodeURIComponent(e)}&model=${encodeURIComponent(t)}&per_page=100`)]);if(!a.ok||!s.ok)throw new Error("Error al cargar vehículos");const n=await a.json(),i=await s.json(),r=n.data||n,o=i.data||i;this.allVehicles=r.map((e=>{const t=o.find((t=>t.brand===e.brand&&t.model===e.model&&t.year===e.year&&t.engine===e.engine));return{...e,mye_id:t?t.id:null}})).filter((e=>null!==e.mye_id)),this.filteredVehicles=[...this.allVehicles],await this.populateFilters(e,t),this.displayVehicles()}catch(t){console.error("Error:",t),a.innerHTML=`\n \n
\n
Error al cargar vehículos \n
${t.message}
\n
\n Volver a modelos\n \n
\n `}}async populateFilters(e,t){try{const[a,s]=await Promise.all([fetch(`/api/years?brand=${encodeURIComponent(e)}&model=${encodeURIComponent(t)}`),fetch(`/api/engines?brand=${encodeURIComponent(e)}&model=${encodeURIComponent(t)}`)]);if(a.ok){const e=await a.json();document.getElementById("yearFilter").innerHTML='Todos los años '+e.map((e=>`${e} `)).join("")}if(s.ok){const e=await s.json();document.getElementById("engineFilter").innerHTML='Todos los motores '+e.map((e=>`${e} `)).join("")}}catch(e){console.error("Error populating filters:",e)}}bindFilterEvents(){document.getElementById("yearFilter").addEventListener("change",(()=>{this.applyFilters()})),document.getElementById("engineFilter").addEventListener("change",(()=>{this.applyFilters()}))}applyFilters(){const e=document.getElementById("yearFilter").value,t=document.getElementById("engineFilter").value;this.filteredVehicles=this.allVehicles.filter((a=>!(e&&a.year.toString()!==e||t&&a.engine!==t))),this.displayVehicles()}getEngineConfig(e){if(!e)return"N/A";const t=e.toUpperCase(),a=t.match(/V(\d+)/);if(a)return`V${a[1]}`;const s=t.match(/I(\d+)|INLINE[- ]?(\d+)/);if(s)return`I${s[1]||s[2]}`;const n=t.match(/H(\d+)|FLAT[- ]?(\d+)/);if(n)return`H${n[1]||n[2]}`;const i=t.match(/W(\d+)/);if(i)return`W${i[1]}`;const r=t.match(/(\d)[- ]?CYL/);return r?`${r[1]} Cil`:t.includes("ELECTRIC")?"EV":t.includes("ROTARY")?"Rotary":"N/A"}formatDisplacement(e){if(!e||0===e)return"N/A";return`${(e/1e3).toFixed(1)}L`}formatFuelType(e){return{gasoline:"Gasolina",diesel:"Diésel",electric:"Eléctrico",hybrid:"Híbrido",other:"Otro"}[e]||e||"N/A"}displayVehicles(){const e=document.getElementById("mainContent");document.getElementById("resultCount").textContent=`${this.filteredVehicles.length} resultado${1!==this.filteredVehicles.length?"s":""}`,0!==this.filteredVehicles.length?e.innerHTML=`\n ${this.filteredVehicles.map((e=>`\n
\n \n
\n
\n
\n
\n
${this.formatFuelType(e.fuel_type)}
\n
\n
\n
\n
${e.power_hp||"N/A"} HP
\n
\n
\n
\n
${e.torque_nm||"N/A"} Nm
\n
\n
\n
\n
${this.formatDisplacement(e.displacement_cc)}
\n
\n
\n
\n
${e.cylinders||"N/A"} Cil
\n
\n
\n
\n
${this.getEngineConfig(e.engine)}
\n
\n
\n ${e.trim_level&&"unknown"!==e.trim_level?`\n
\n ${e.trim_level} \n
\n `:""}\n
\n Ver Partes\n \n
\n
\n `)).join("")}\n
`:e.innerHTML='\n \n
\n
No se encontraron vehículos \n
Intenta ajustar los filtros
\n
\n '}goToBrands(){this.showBrands()}showFilters(){document.getElementById("filtersBar").classList.add("visible"),document.getElementById("yearFilter").value="",document.getElementById("engineFilter").value=""}hideFilters(){document.getElementById("filtersBar").classList.remove("visible")}async navigateToVehicle(e,t,a,s){this.selectedBrand=t,this.selectedModel=a,this.selectedYear=s,this.allVehicles.find((t=>t.mye_id===e))||this.allVehicles.push({mye_id:e,brand:t,model:a,year:s}),await this.goToCategories(e)}async navigateToVehicleCategory(e,t,a,s,n){if(this.selectedBrand=t,this.selectedModel=a,this.selectedYear=s,this.allVehicles.find((t=>t.mye_id===e))||this.allVehicles.push({mye_id:e,brand:t,model:a,year:s}),this.selectedVehicleId=e,0===this.allCategories.length)try{const e=await fetch("/api/categories");e.ok&&(this.allCategories=await e.json())}catch(e){console.error("Error loading categories:",e)}await this.goToGroups(n)}async goToCategories(e){if(!e||"null"===e||"undefined"===e){return void(document.getElementById("mainContent").innerHTML=`\n \n
\n
Vehículo sin partes disponibles \n
Este vehículo no tiene partes registradas en el catálogo.
\n
\n Volver a modelos\n \n
\n `)}this.currentView="categories",this.selectedVehicleId=e,this.selectedCategory=null;const t=this.allVehicles.find((t=>t.mye_id===e));t&&(this.selectedYear=t.year),this.updateBreadcrumb(),this.hideFilters();const a=document.getElementById("mainContent");a.innerHTML='\n \n \n
Cargando categorías... \n \n ';try{const t=await fetch(`/api/vehicles/${e}/categories`);if(!t.ok)throw new Error("Error al cargar categorías");this.allCategories=await t.json(),this.displayCategories()}catch(e){console.error("Error:",e),a.innerHTML=`\n \n
\n
Error al cargar categorías \n
${e.message}
\n
\n Volver a vehículos\n \n
\n `}}displayCategories(){const e=document.getElementById("mainContent");0!==this.allCategories.length?(e.innerHTML=`\n ${this.allCategories.map((e=>{const t=e.icon_name||"fa-cog",a=e.name_es||e.name;return`\n
\n
\n \n
\n
${a}
\n
\n ${e.children?e.children.length+" subcategorías":""}\n
\n
\n `})).join("")}\n
\n \n \n Volver a vehículos\n \n
`,this.makeCardsAccessible("#mainContent",".category-card")):e.innerHTML=`\n \n
\n
No hay categorías disponibles \n
Este vehículo no tiene partes registradas
\n
\n Volver a vehículos\n \n
\n `}async goToGroups(e){this.currentView="groups";const t=this.allCategories.find((t=>t.id===e));this.selectedCategory=t||{id:e,name:"Categoria"},this.selectedGroup=null,this.updateBreadcrumb(),this.hideFilters();const a=document.getElementById("mainContent");a.innerHTML='\n \n \n
Cargando grupos... \n \n ';try{let t;t=this.selectedVehicleId?`/api/vehicles/${this.selectedVehicleId}/groups?category_id=${e}`:`/api/categories/${e}/groups`;const a=await fetch(t);if(!a.ok)throw new Error("Error al cargar grupos");const s=await a.json();let n=[];if(this.selectedVehicleId&&(10===e||11===e))try{const t=await fetch(`/api/vehicles/${this.selectedVehicleId}/diagrams/by-category?category_id=${e}`);if(t.ok){const e=await t.json();for(const t of e)n.push(...t.diagrams)}}catch(e){console.error("Error loading diagrams for strip:",e)}this.displayGroups(s,e,n)}catch(e){console.error("Error:",e),a.innerHTML=`\n \n
\n
Error al cargar grupos \n
${e.message}
\n
\n Volver a categorías\n \n
\n `}}displayGroups(e,t,a=[]){const s=document.getElementById("mainContent");if(0===e.length&&0===a.length)return void(s.innerHTML=`\n \n \n
No hay grupos en esta categoría \n \n Volver a categorías\n \n \n `);let n="";a.length>0&&(this._currentDiagramList=a,n=`\n `),s.innerHTML=`\n ${this.selectedCategory.name_es||this.selectedCategory.name} \n ${n}\n \n ${e.map((e=>`\n
\n
\n \n
\n
${e.name_es||e.name}
\n
\n \n Ver Partes\n \n \n Diagramas\n \n
\n
\n `)).join("")}\n
\n \n \n Volver a categorías\n \n
`,this.makeCardsAccessible("#mainContent",".category-card")}async goToParts(e){this.currentView="parts",this.selectedGroupId=e;try{const t=await fetch(`/api/categories/${this.selectedCategory?this.selectedCategory.id:0}/groups`);if(t.ok){const a=await t.json();this.selectedGroup=a.find((t=>t.id===e))||{id:e,name:"Grupo"}}}catch(t){console.error("Error fetching group details:",t),this.selectedGroup={id:e,name:"Grupo"}}this.updateBreadcrumb(),this.hideFilters();const t=document.getElementById("mainContent");t.innerHTML='\n \n \n
Cargando partes... \n \n ';try{let t;t=this.selectedVehicleId?`/api/vehicles/${this.selectedVehicleId}/parts?group_id=${e}`:`/api/parts?group_id=${e}`;const a=await fetch(t);if(!a.ok)throw new Error("Error al cargar partes");const s=await a.json();this.allParts=Array.isArray(s)?s:s.data||s,this.displayParts()}catch(e){console.error("Error:",e),t.innerHTML=`\n \n
\n
Error al cargar partes \n
${e.message}
\n
\n Volver a grupos\n \n
\n `}}displayParts(){const e=document.getElementById("mainContent");0!==this.allParts.length?e.innerHTML=`\n \n
\n \n \n OEM # \n Nombre \n Grupo \n Acción \n \n \n \n ${this.allParts.map((e=>`\n \n ${e.oem_part_number||"N/A"} \n ${e.name_es||e.name||"Sin nombre"} \n ${e.group_name||"N/A"} \n \n \n Ver\n \n \n \n `)).join("")}\n \n
\n
\n \n \n Volver a grupos\n \n
\n `:e.innerHTML=`\n \n
\n
No hay partes disponibles \n
Este grupo no tiene partes registradas aún
\n
\n Volver a grupos\n \n
\n `}async showPartDetail(e){const t=document.getElementById("partDetailContent");t.innerHTML='\n \n
\n
Cargando detalles...
\n
\n ';this.openModalWithFocus("partDetailModal");try{const[a,s,n]=await Promise.all([fetch(`/api/parts/${e}`),fetch(`/api/parts/${e}/alternatives`),fetch(`/api/parts/${e}/cross-references`)]);if(!a.ok)throw new Error("Error al cargar detalle de la parte");const i=await a.json(),r=s.ok?await s.json():[],o=n.ok?await n.json():[];t.innerHTML=`\n \n
\n
${i.name_es||i.name||"Sin nombre"} \n \n
\n ${i.image_url?`\n \n
\n
\n `:""}\n \n Número OEM \n ${i.oem_part_number||"N/A"} \n
\n \n Categoría \n ${i.category_name_es||i.category_name||"N/A"} \n
\n \n Grupo \n ${i.group_name_es||i.group_name||"N/A"} \n
\n ${i.description||i.description_es?`\n \n Descripción \n ${i.description_es||i.description} \n
\n `:""}\n\n \x3c!-- FASE 2: Cross-Referencias Section --\x3e\n ${this.renderCrossReferences(o)}\n\n \x3c!-- FASE 2: Alternativas Aftermarket Section --\x3e\n ${this.renderAlternatives(r)}\n `}catch(e){console.error("Error:",e),t.innerHTML=`\n \n `}}renderCrossReferences(e){if(!e||0===e.length)return"";return`\n \n
Cross-Referencias\n
\n ${e.map((e=>`${e.cross_reference_number||e.part_number||e}${e.brand?` (${e.brand})`:""} `)).join("")}\n
\n
\n `}renderAlternatives(e){if(!e||0===e.length)return"";return`\n \n
Alternativas Aftermarket\n
\n \n \n Marca \n Número de Parte \n Nombre \n Calidad \n Precio \n \n \n \n ${e.map((e=>`\n \n ${e.brand||"N/A"} \n ${e.part_number||"N/A"} \n ${e.name_es||e.name||"N/A"} \n ${this.getQualityBadge(e.quality_tier)} \n ${this.formatPrice(e.price)} \n \n `)).join("")}\n \n
\n
\n `}getQualityBadge(e){const t={economy:{class:"quality-economy",label:"Económico"},standard:{class:"quality-standard",label:"Estándar"},premium:{class:"quality-premium",label:"Premium"},oem:{class:"quality-oem",label:"OEM"}},a=t[e?.toLowerCase()]||t.standard;return`${a.label} `}formatPrice(e){return null==e?"N/A":new Intl.NumberFormat("es-MX",{style:"currency",currency:"MXN"}).format(e)}async searchPartNumber(){const e=document.getElementById("searchInput").value.trim();if(!e)return;if(17===e.length&&/^[A-HJ-NPR-Z0-9]{17}$/i.test(e)&&confirm("El texto parece ser un VIN. ¿Deseas decodificarlo?"))return document.getElementById("vinInput").value=e.toUpperCase(),void this.openVinDecoder();const t=document.getElementById("searchResultsContent");t.innerHTML=`\n \n
\n
Buscando "${e}"...
\n
\n `;this.openModalWithFocus("searchResultsModal");try{let t;t=await fetch(`/api/search/part-number/${encodeURIComponent(e)}`);let a=[];if(t.ok&&(a=await t.json()),0===a.length){const t=await fetch(`/api/search?q=${encodeURIComponent(e)}`);if(t.ok){const e=await t.json();a=e.parts||e||[]}}this.showSearchResults(a,e)}catch(e){console.error("Error:",e),t.innerHTML=`\n \n
\n
Error al buscar: ${e.message}
\n
\n `}}showSearchResults(e,t){const a=document.getElementById("searchResultsContent");if(document.getElementById("searchResultsModalLabel").innerHTML=` Resultados para "${t}"`,!e||0===e.length)return void(a.innerHTML=`\n \n
\n
No se encontraron resultados para "${t}"
\n
\n `);const s=e.map((e=>`\n \n
\n
\n
\n ${e.oem_part_number||e.part_number||"N/A"} \n
\n
${e.name_es||e.name||"Sin nombre"}
\n
\n
\n ${e.quality_tier?this.getQualityBadge(e.quality_tier):""}\n ${e.brand?`
${e.brand}
`:""}\n
\n
\n
\n `)).join("");a.innerHTML=`\n ${e.length} resultado${1!==e.length?"s":""} encontrado${1!==e.length?"s":""}
\n \n ${s}\n
\n `,this.makeCardsAccessible("#searchResultsContent",".search-result-item")}showPartDetailFromSearch(e){const t=document.getElementById("searchResultsModal");t&&t.classList.remove("active"),setTimeout((()=>{this.showPartDetail(e)}),300)}async goToDiagrams(e){const t=document.getElementById("mainContent");t.innerHTML='\n \n \n
Cargando diagramas... \n \n ';try{const t=await fetch(`/api/groups/${e}/diagrams`);if(!t.ok)throw new Error("Error al cargar diagramas");const a=await t.json();this.displayDiagramThumbnails(a,e)}catch(e){console.error("Error:",e),t.innerHTML=`\n \n
\n
Error al cargar diagramas \n
${e.message}
\n
\n Volver a grupos\n \n
\n `}}displayDiagramThumbnails(e,t){const a=document.getElementById("mainContent");e&&0!==e.length?(a.innerHTML=`\n \n \n
\n ${e.map((e=>`\n
\n
\n ${e.thumbnail_url?`
`:'
'}\n
\n
${e.name_es||e.name||"Diagrama"}
\n
\n `)).join("")}\n
\n
\n \n \n Volver a grupos\n \n
\n `,this.makeCardsAccessible("#mainContent",".diagram-thumbnail")):a.innerHTML=`\n \n
\n
No hay diagramas disponibles \n
Este grupo no tiene diagramas registrados
\n
\n Volver a grupos\n \n
\n `}async showDiagram(e){const t=document.getElementById("diagramModalContent"),a=document.getElementById("diagramModalTitle");t.innerHTML='\n \n
\n
Cargando diagrama...
\n
\n ';this.openModalWithFocus("diagramModal");try{const t=await fetch(`/api/diagrams/${e}`);if(!t.ok)throw new Error("Error al cargar diagrama");const s=await t.json();a.innerHTML=` ${s.name_es||s.name||"Diagrama"}`,this.currentDiagramZoom=1,this.renderDiagramWithHotspots(s)}catch(e){console.error("Error:",e),t.innerHTML=`\n \n
\n
Error al cargar diagrama: ${e.message}
\n
\n `}}renderDiagramWithHotspots(e){const t=document.getElementById("diagramModalContent"),a=e.hotspots||[];t.innerHTML=`\n \n \n
\n ${e.svg_content?e.svg_content:e.image_url?`
`:'
\n
\n
No hay imagen de diagrama disponible
\n
'}\n ${a.map(((e,t)=>this.renderHotspot(e,t))).join("")}\n
\n
\n ${a.length>0?`\n \n
Leyenda de Partes\n
\n ${a.map(((e,t)=>`\n
\n ${t+1} \n ${e.name_es||e.name||e.label||"Parte "+(t+1)} \n
\n `)).join("")}\n
\n
\n `:""}\n `}renderHotspot(e,t){const a=e.x||e.position_x||0,s=e.y||e.position_y||0,n=e.width||30,i=e.height||30;return`\n \n
\n ${t+1}\n
\n
\n \n \n
\n `}onHotspotClick(e){if(e.part_id){const t=document.getElementById("diagramModal");t&&t.classList.remove("active"),setTimeout((()=>{this.showPartDetail(e.part_id)}),300)}else{const t=e.name_es||e.name||e.label||"Parte",a=e.description_es||e.description||"";alert(`${t}${a?"\n\n"+a:""}`)}}zoomDiagram(e){const t=document.getElementById("diagramWrapper");t&&(this.currentDiagramZoom=0===e?1:Math.max(.5,Math.min(2,this.currentDiagramZoom+e)),t.style.transform=`scale(${this.currentDiagramZoom})`)}openDiagramViewer(e,t){this._dvCurrentIndex="number"==typeof t?t:-1,this._dvDiagramList=this._currentDiagramList||[],this._dvZoom=1,this._dvDragging=!1;document.getElementById("diagramViewerOverlay").classList.add("active"),document.body.style.overflow="hidden",this._loadDiagramInViewer(e),this._bindDiagramViewerEvents()}closeDiagramViewer(){document.getElementById("diagramViewerOverlay").classList.remove("active"),document.body.style.overflow="",this._unbindDiagramViewerEvents()}async _loadDiagramInViewer(e){const t=document.getElementById("dvTitle"),a=document.getElementById("dvSubtitle"),s=document.getElementById("dvImgWrapper"),n=document.getElementById("dvImg"),i=document.getElementById("dvPartsList"),r=document.getElementById("dvPartsCount");i.innerHTML='',r.textContent="...";try{const[i,r]=await Promise.all([fetch(`/api/diagrams/${e}`),fetch(`/api/diagrams/${e}/parts${this.selectedVehicleId?"?mye_id="+this.selectedVehicleId:""}`)]),o=await i.json(),l=await r.json(),d=(o.name||"")[0],c="F"===d?"Suspensión Delantera":"S"===d?"Dirección":"R"===d?"Suspensión Trasera":o.group_name||"";t.textContent=o.name||"Diagrama",a.textContent=o.name_es||c;const m=o.image_url||(o.image_path?"/"+o.image_path:"");n.src=m,n.alt=o.name_es||o.name,this._dvZoom=1,s.style.transform="",s.classList.remove("zoomed"),document.getElementById("dvZoomLevel").textContent="100%",this._renderViewerHotspots(o.hotspots||[],s),this._renderViewerParts(l,o.hotspots||[]);const h=document.getElementById("dvPrevBtn"),p=document.getElementById("dvNextBtn");h.disabled=this._dvCurrentIndex<=0,p.disabled=this._dvCurrentIndex<0||this._dvCurrentIndex>=this._dvDiagramList.length-1,h.style.opacity=h.disabled?"0.3":"1",p.style.opacity=p.disabled?"0.3":"1"}catch(e){console.error("Error loading diagram in viewer:",e),i.innerHTML=''}}_renderViewerHotspots(e,t){t.querySelectorAll(".hotspot-marker").forEach((e=>e.remove())),e&&0!==e.length&&e.forEach(((e,a)=>{const s=(e.coords||"").split(",");if(s.length<2)return;const n=parseFloat(s[0]),i=parseFloat(s[1]);if(isNaN(n)||isNaN(i))return;const r=document.createElement("div");r.className="hotspot-marker pulse",r.style.left=n+"%",r.style.top=i+"%",r.dataset.partId=e.part_id||"",r.dataset.callout=e.callout_number||a+1,r.title=e.part_name||e.label||"Parte "+(a+1),r.innerHTML=`${e.callout_number||a+1} `,r.addEventListener("click",(()=>{this._highlightPartInList(e.part_id),t.querySelectorAll(".hotspot-marker").forEach((e=>e.classList.remove("active"))),r.classList.add("active")})),t.appendChild(r)}))}_renderViewerParts(e,t){const a=document.getElementById("dvPartsList");if(document.getElementById("dvPartsCount").textContent=e.length,!e||0===e.length)return void(a.innerHTML='');const s={};(t||[]).forEach(((e,t)=>{e.part_id&&(s[e.part_id]=e.callout_number||t+1)}));const n={};e.forEach((e=>{const t=e.group_name_es||e.group_name||"Otros";n[t]||(n[t]=[]),n[t].push(e)}));let i="";for(const[e,t]of Object.entries(n)){i+=`${e}
`;for(const e of t){const t=s[e.id];let a="";e.cross_references&&e.cross_references.length>0&&(a=`${e.cross_references.map((e=>`${e.number} `)).join("")}
`),i+=`\n \n
\n ${t?`
${t} `:""}\n
${e.part_number||e.oem_part_number}
\n
\n
${e.name_es||e.name||""}
\n ${a}\n
`}}a.innerHTML=i}_highlightPartInList(e){if(!e)return;const t=document.getElementById("dvPartsList");t.querySelectorAll(".dv-part-item").forEach((e=>e.classList.remove("highlighted")));const a=t.querySelector(`.dv-part-item[data-part-id="${e}"]`);a&&(a.classList.add("highlighted"),a.scrollIntoView({behavior:"smooth",block:"nearest"}))}_onViewerPartClick(e){this._highlightPartInList(e);document.getElementById("dvImgWrapper").querySelectorAll(".hotspot-marker").forEach((t=>{t.classList.remove("active"),t.dataset.partId==e&&t.classList.add("active")}))}_dvNavigate(e){const t=this._dvCurrentIndex+e;if(t<0||t>=this._dvDiagramList.length)return;this._dvCurrentIndex=t;const a=this._dvDiagramList[t];a&&this._loadDiagramInViewer(a.id)}_dvSetZoom(e){this._dvZoom=Math.max(.25,Math.min(4,e));const t=document.getElementById("dvImgWrapper");1!==this._dvZoom?(t.classList.add("zoomed"),t.style.transform=`scale(${this._dvZoom})`):(t.classList.remove("zoomed"),t.style.transform=""),document.getElementById("dvZoomLevel").textContent=`${Math.round(100*this._dvZoom)}%`}_bindDiagramViewerEvents(){this._dvBound||(this._dvBound=!0,this._dvHandlers={close:()=>this.closeDiagramViewer(),prev:()=>this._dvNavigate(-1),next:()=>this._dvNavigate(1),zoomIn:()=>this._dvSetZoom(this._dvZoom+.25),zoomOut:()=>this._dvSetZoom(this._dvZoom-.25),zoomFit:()=>this._dvSetZoom(1),keydown:e=>{document.getElementById("diagramViewerOverlay").classList.contains("active")&&("Escape"===e.key&&this.closeDiagramViewer(),"ArrowLeft"===e.key&&this._dvNavigate(-1),"ArrowRight"===e.key&&this._dvNavigate(1),"+"!==e.key&&"="!==e.key||this._dvSetZoom(this._dvZoom+.25),"-"===e.key&&this._dvSetZoom(this._dvZoom-.25))},wheel:e=>{if(!document.getElementById("diagramViewerOverlay").classList.contains("active"))return;e.preventDefault();const t=e.deltaY>0?-.15:.15;this._dvSetZoom(this._dvZoom+t)},partsFilter:e=>{const t=e.target.value.toLowerCase();document.querySelectorAll("#dvPartsList .dv-part-item").forEach((e=>{e.style.display=e.textContent.toLowerCase().includes(t)?"":"none"}))},mousedown:e=>{if(this._dvZoom<=1)return;this._dvDragging=!0,this._dvDragStart={x:e.clientX,y:e.clientY};const t=document.getElementById("dvImgContainer");this._dvScrollStart={x:t.scrollLeft,y:t.scrollTop},t.style.cursor="grabbing"},mousemove:e=>{if(!this._dvDragging)return;const t=document.getElementById("dvImgContainer");t.scrollLeft=this._dvScrollStart.x-(e.clientX-this._dvDragStart.x),t.scrollTop=this._dvScrollStart.y-(e.clientY-this._dvDragStart.y)},mouseup:()=>{this._dvDragging=!1;const e=document.getElementById("dvImgContainer");e&&(e.style.cursor="")}},document.getElementById("dvCloseBtn").addEventListener("click",this._dvHandlers.close),document.getElementById("dvPrevBtn").addEventListener("click",this._dvHandlers.prev),document.getElementById("dvNextBtn").addEventListener("click",this._dvHandlers.next),document.getElementById("dvZoomIn").addEventListener("click",this._dvHandlers.zoomIn),document.getElementById("dvZoomOut").addEventListener("click",this._dvHandlers.zoomOut),document.getElementById("dvZoomFit").addEventListener("click",this._dvHandlers.zoomFit),document.getElementById("dvPartsFilter").addEventListener("input",this._dvHandlers.partsFilter),document.addEventListener("keydown",this._dvHandlers.keydown),document.getElementById("dvImgContainer").addEventListener("wheel",this._dvHandlers.wheel,{passive:!1}),document.getElementById("dvImgContainer").addEventListener("mousedown",this._dvHandlers.mousedown),window.addEventListener("mousemove",this._dvHandlers.mousemove),window.addEventListener("mouseup",this._dvHandlers.mouseup))}_unbindDiagramViewerEvents(){this._dvBound&&(this._dvBound=!1,document.getElementById("dvCloseBtn")?.removeEventListener("click",this._dvHandlers.close),document.getElementById("dvPrevBtn")?.removeEventListener("click",this._dvHandlers.prev),document.getElementById("dvNextBtn")?.removeEventListener("click",this._dvHandlers.next),document.getElementById("dvZoomIn")?.removeEventListener("click",this._dvHandlers.zoomIn),document.getElementById("dvZoomOut")?.removeEventListener("click",this._dvHandlers.zoomOut),document.getElementById("dvZoomFit")?.removeEventListener("click",this._dvHandlers.zoomFit),document.getElementById("dvPartsFilter")?.removeEventListener("input",this._dvHandlers.partsFilter),document.removeEventListener("keydown",this._dvHandlers.keydown),document.getElementById("dvImgContainer")?.removeEventListener("wheel",this._dvHandlers.wheel),document.getElementById("dvImgContainer")?.removeEventListener("mousedown",this._dvHandlers.mousedown),window.removeEventListener("mousemove",this._dvHandlers.mousemove),window.removeEventListener("mouseup",this._dvHandlers.mouseup))}openVinDecoder(){document.getElementById("vinResult").innerHTML="",this.openModalWithFocus("vinDecoderModal")}async decodeVin(){const e=document.getElementById("vinInput").value.trim().toUpperCase(),t=document.getElementById("vinResult");if(e)if(17===e.length)if(/[IOQ]/i.test(e))t.innerHTML='\n \n El VIN contiene caracteres invalidos. Las letras I, O y Q no se permiten en VINs.\n
\n ';else if(/^[A-HJ-NPR-Z0-9]{17}$/i.test(e)){t.innerHTML='\n \n
\n
Decodificando VIN...
\n
\n ';try{const t=await fetch(`/api/vin/decode/${encodeURIComponent(e)}`);if(!t.ok){const e=await t.json().catch((()=>({})));throw new Error(e.detail||e.message||"Error al decodificar VIN")}const a=await t.json();this.showVinResult(a,e)}catch(e){console.error("Error:",e),t.innerHTML=`\n \n ${e.message}\n
\n `}}else t.innerHTML='\n \n El VIN contiene caracteres invalidos. Solo se permiten letras (excepto I, O, Q) y numeros.\n
\n ';else t.innerHTML=`\n \n El VIN debe tener exactamente 17 caracteres (actual: ${e.length})\n
\n `;else t.innerHTML='\n \n Por favor ingresa un VIN\n
\n '}showVinResult(e,t){const a=document.getElementById("vinResult"),s=e.vehicle||e,n=s.make||s.brand||"Desconocido",i=s.model||"Desconocido",r=s.year||s.model_year||"Desconocido",o=s.engine||s.engine_description||"N/A",l=s.trim||s.trim_level||"",d=(s.body_type||s.body_class,s.drive_type||s.drivetrain||"N/A"),c=s.fuel_type||"N/A",m=s.transmission||"N/A",h=s.country||s.plant_country||"N/A",p=e.matched||e.database_match||s.mye_id,g=s.mye_id||e.mye_id;let v="";v=p&&g?`\n \n
\n
\n \n Vehiculo encontrado en la base de datos \n
\n
\n Ver Partes\n \n
\n
\n `:`\n \n
\n
\n \n Vehiculo no encontrado en la base de datos \n
\n
\n Buscar Manualmente\n \n
\n
\n `,a.innerHTML=`\n \n \n\n
${r} ${n} ${i} ${l} \n\n
\n
\n
\n Marca \n ${n} \n
\n
\n Modelo \n ${i} \n
\n
\n Año \n ${r} \n
\n
\n Motor \n ${o} \n
\n
\n
\n
\n Combustible \n ${c} \n
\n
\n Transmision \n ${m} \n
\n
\n Traccion \n ${d} \n
\n
\n Pais \n ${h} \n
\n
\n
\n\n ${v}\n
\n `}async viewVinParts(e,t){const a=document.getElementById("vinDecoderModal");a&&a.classList.remove("active");const s=document.getElementById("searchResultsContent");document.getElementById("searchResultsModalLabel").innerHTML=` Partes para VIN: ${e.substring(0,8)}...`,s.innerHTML='\n \n
\n
Cargando partes...
\n
\n ';this.openModalWithFocus("searchResultsModal");try{const a=await fetch(`/api/vin/${encodeURIComponent(e)}/parts`);if(!a.ok)throw new Error("Error al cargar partes");const s=await a.json(),n=s.parts||s;this.displayVinParts(n,e,t)}catch(e){console.error("Error:",e),s.innerHTML=t?`\n \n No se encontraron partes especificas para este VIN.\n \n \n Ver Categorias del Vehiculo\n \n
\n `:`\n \n
\n
Error al cargar partes: ${e.message}
\n
\n `}}displayVinParts(e,t,a){const s=document.getElementById("searchResultsContent");if(!e||0===e.length)return void(s.innerHTML=`\n \n
\n
No se encontraron partes para este VIN
\n ${a?`\n
\n Ver Categorias del Vehiculo\n \n `:""}\n
\n `);const n={};e.forEach((e=>{const t=e.category_name_es||e.category_name||"Sin Categoria";n[t]||(n[t]=[]),n[t].push(e)}));let i=`${e.length} parte${1!==e.length?"s":""} encontrada${1!==e.length?"s":""}
`;for(const[e,t]of Object.entries(n))i+=`\n \n
${e}\n
\n ${t.map((e=>`\n
\n
\n
\n
\n ${e.oem_part_number||e.part_number||"N/A"} \n
\n
${e.name_es||e.name||"Sin nombre"}
\n
\n
\n ${e.quality_tier?this.getQualityBadge(e.quality_tier):""}\n ${e.group_name_es||e.group_name?`
${e.group_name_es||e.group_name}
`:""}\n
\n
\n
\n `)).join("")}\n
\n
\n `;a&&(i+=`\n \n \n Ver Todas las Categorias\n \n
\n `),s.innerHTML=i}searchManuallyFromVin(e,t,a){const s=bootstrap.Modal.getInstance(document.getElementById("vinDecoderModal"));s&&s.hide(),setTimeout((async()=>{try{const t=await fetch("/api/brands");if(t.ok){const a=(await t.json()).find((t=>t.toLowerCase()===e.toLowerCase()||t.toLowerCase().includes(e.toLowerCase())||e.toLowerCase().includes(t.toLowerCase())));if(a)return void this.goToModels(a)}alert(`La marca "${e}" no se encontro en la base de datos. Mostrando todas las marcas disponibles.`),this.goToBrands()}catch(e){console.error("Error:",e),this.goToBrands()}}),300)}}let dashboard;document.addEventListener("DOMContentLoaded",(()=>{dashboard=new VehicleDashboard}));