// Linux BenchTools - Devices Two-Panel Layout
(function() {
  'use strict';

// Use utilities from global scope directly - avoid redeclaration
const utils = window.BenchUtils;
const apiClient = window.BenchAPI;

let allDevices = [];
let selectedDeviceId = null;
let isEditing = false;
let currentDevice = null;
let editingNotes = false;
let editingUpgradeNotes = false;
let editingPurchase = false;

// Section icon mapping - uses data-icon with IconManager
const SECTION_ICON_NAMES = {
  motherboard: 'motherboard',
  cpu: 'cpu',
  ram: 'memory',
  storage: 'hdd',
  gpu: 'gpu',
  network: 'network',
  usb: 'usb',
  pci: 'pci',
  os: 'desktop',
  shares: 'folder',
  benchmarks: 'chart-line',
  metadata: 'info-circle',
  images: 'image',
  pdf: 'file-pdf',
  links: 'link',
  tags: 'tag',
  notes: 'edit',
  purchase: 'shopping-cart',
  upgrade: 'rocket'
};

function getSectionIcon(key, altText) {
  const iconName = SECTION_ICON_NAMES[key];
  if (!iconName) return '';
  const safeAlt = utils.escapeHtml(altText || key);
  return `<span class="section-icon" data-icon="${iconName}" title="${safeAlt}"></span>`;
}

// Load devices
async function loadDevices() {
  const listContainer = document.getElementById('deviceList');

  try {
    console.log('🔄 Loading devices from API...');
    console.log('API URL:', apiClient.baseURL);

    const data = await apiClient.getDevices({ page_size: 100 }); // Get all devices (max allowed)

    console.log('✅ Devices loaded:', data);

    allDevices = data.items || [];

    if (allDevices.length === 0) {
      listContainer.innerHTML = '<div style="padding: 1rem; text-align: center; color: var(--text-secondary);">📊<br>Aucun device</div>';
      return;
    }

    // Sort by global_score descending
    allDevices.sort((a, b) => {
      const scoreA = a.last_benchmark?.global_score ?? -1;
      const scoreB = b.last_benchmark?.global_score ?? -1;
      return scoreB - scoreA;
    });

    console.log('📋 Rendering', allDevices.length, 'devices');
    renderDeviceList();

    // Auto-select first device if none selected
    if (!selectedDeviceId && allDevices.length > 0) {
      selectDevice(allDevices[0].id);
    }

  } catch (error) {
    console.error('❌ Failed to load devices:', error);
    console.error('Error details:', error.message);
    listContainer.innerHTML = `
      <div style="padding: 1rem; color: var(--color-danger); font-size: 0.85rem;">
        <div style="font-weight: 600; margin-bottom: 0.5rem;">❌ Erreur</div>
        <div>${error.message || 'Erreur de chargement'}</div>
        <div style="margin-top: 0.5rem; font-size: 0.75rem;">
          Backend: ${apiClient.baseURL}
        </div>
      </div>
    `;
  }
}

// Render device list (left panel)
function renderDeviceList() {
  const listContainer = document.getElementById('deviceList');

  listContainer.innerHTML = allDevices.map(device => {
    const globalScore = device.last_benchmark?.global_score;
    const isSelected = device.id === selectedDeviceId;
    const hostnameEscaped = (device.hostname || '').replace(/'/g, "\\'").replace(/"/g, '\\"');

    const scoreText = formatScoreValue(globalScore);

    const scoreClass = globalScore !== null && globalScore !== undefined
      ? utils.getScoreBadgeClass(globalScore)
      : 'badge';

    return `
      <div
        class="device-list-item ${isSelected ? 'selected' : ''}"
        onclick="selectDevice(${device.id})"
        style="
          padding: 0.75rem;
          margin-bottom: 0.5rem;
          background: ${isSelected ? 'var(--color-primary-alpha)' : 'var(--bg-secondary)'};
          border: 1px solid ${isSelected ? 'var(--color-primary)' : 'var(--border-color)'};
          border-radius: 6px;
          cursor: pointer;
          transition: all 0.2s;
        "
        onmouseover="if (!this.classList.contains('selected')) this.style.background='var(--bg-hover)'"
        onmouseout="if (!this.classList.contains('selected')) this.style.background='var(--bg-secondary)'"
      >
        <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.25rem;">
          <div style="font-weight: 600; font-size: 0.95rem; color: var(--text-primary);">
            ${utils.escapeHtml(device.hostname || 'N/A')}
          </div>
          <div style="display: flex; align-items: center; gap: 0.35rem;">
            <span class="${scoreClass}" style="font-size: 0.75rem; padding: 0.2rem 0.5rem;">
              ${scoreText}
            </span>
            <button type="button" class="device-list-delete" title="Supprimer ce device" onclick="event.stopPropagation(); deleteDeviceFromList(event, ${device.id}, '${hostnameEscaped}')">🗑️</button>
          </div>
        </div>
        ${device.last_benchmark?.run_at ? `
          <div style="font-size: 0.75rem; color: var(--text-secondary);">
            ⏱️ ${utils.formatRelativeTime(device.last_benchmark.run_at)}
          </div>
        ` : '<div style="font-size: 0.75rem; color: var(--color-warning);">⚠️ Pas de benchmark</div>'}
      </div>
    `;
  }).join('');
}

// Select device and display details
async function selectDevice(deviceId) {
  selectedDeviceId = deviceId;
  renderDeviceList(); // Update selection in list

  const detailsContainer = document.getElementById('deviceDetailsContainer');
  detailsContainer.innerHTML = '<div class="loading">Chargement des détails...</div>';

  try {
    const device = await apiClient.getDevice(deviceId);
    renderDeviceDetails(device);
  } catch (error) {
    console.error('Failed to load device details:', error);
    utils.showError(detailsContainer, 'Impossible de charger les détails du device.');
  }
}

// Toggle edit mode
function toggleEditMode() {
  isEditing = !isEditing;
  if (currentDevice) {
    renderDeviceDetails(currentDevice);
  }
}

// Save device changes
async function saveDevice() {
  if (!currentDevice) return;

  const description = document.getElementById('edit-description')?.value || '';
  const location = document.getElementById('edit-location')?.value || '';
  const owner = document.getElementById('edit-owner')?.value || '';
  const assetTag = document.getElementById('edit-asset-tag')?.value || '';
  const tags = document.getElementById('edit-tags')?.value || '';

  try {
    console.log('💾 Saving device changes...');

    const updateData = {
      description: description || null,
      location: location || null,
      owner: owner || null,
      asset_tag: assetTag || null,
      tags: tags || null
    };

    await apiClient.updateDevice(currentDevice.id, updateData);

    console.log('✅ Device updated successfully');

    // Reload device data
    isEditing = false;
    const updatedDevice = await apiClient.getDevice(currentDevice.id);
    currentDevice = updatedDevice;
    renderDeviceDetails(updatedDevice);

    // Reload device list to reflect changes
    await loadDevices();

  } catch (error) {
    console.error('❌ Failed to save device:', error);
    alert('Erreur lors de la sauvegarde: ' + (error.message || 'Erreur inconnue'));
  }
}

async function deleteCurrentDevice() {
  if (!currentDevice) return;

  const confirmed = confirm(`Voulez-vous vraiment supprimer le device "${currentDevice.hostname}" ? Cette action supprimera également ses benchmarks et documents.`);
  if (!confirmed) {
    return;
  }

  try {
    await apiClient.deleteDevice(currentDevice.id);
    utils.showToast('Device supprimé', 'success');

    currentDevice = null;
    selectedDeviceId = null;

    document.getElementById('deviceDetailsContainer').innerHTML = renderEmptyDetailsPlaceholder();

    await loadDevices();
  } catch (error) {
    console.error('❌ Failed to delete device:', error);
    alert('Suppression impossible: ' + (error.message || 'Erreur inconnue'));
  }
}

async function deleteDeviceFromList(event, deviceId, hostname) {
  event.stopPropagation();

  const label = hostname || 'ce device';
  const confirmed = confirm(`Supprimer définitivement "${label}" ? Toutes les données associées seront perdues.`);
  if (!confirmed) {
    return;
  }

  try {
    await apiClient.deleteDevice(deviceId);
    utils.showToast('Device supprimé', 'success');

    if (currentDevice && currentDevice.id === deviceId) {
      currentDevice = null;
      selectedDeviceId = null;
      document.getElementById('deviceDetailsContainer').innerHTML = renderEmptyDetailsPlaceholder();
    }

    await loadDevices();
  } catch (error) {
    console.error('❌ Failed to delete device from list:', error);
    alert('Suppression impossible: ' + (error.message || 'Erreur inconnue'));
  }
}

async function reloadCurrentDevice() {
  if (!currentDevice) return;
  const refreshed = await apiClient.getDevice(currentDevice.id);
  currentDevice = refreshed;
  renderDeviceDetails(refreshed);
}

function startNotesEdit() {
  if (!currentDevice) return;
  editingNotes = true;
  renderDeviceDetails(currentDevice);
}

function cancelNotesEdit() {
  editingNotes = false;
  renderDeviceDetails(currentDevice);
}

async function saveNotes() {
  if (!currentDevice) return;
  const textarea = document.getElementById('notes-editor');
  const value = textarea ? textarea.value.trim() : '';
  try {
    await apiClient.updateDevice(currentDevice.id, { description: value || null });
    editingNotes = false;
    await reloadCurrentDevice();
    utils.showToast('Notes sauvegardées', 'success');
  } catch (error) {
    console.error('Failed to save notes:', error);
    utils.showToast(error.message || 'Échec de la sauvegarde des notes', 'error');
  }
}

async function clearNotes() {
  if (!currentDevice) return;
  if (!confirm('Supprimer les notes ?')) return;
  try {
    await apiClient.updateDevice(currentDevice.id, { description: null });
    editingNotes = false;
    await reloadCurrentDevice();
    utils.showToast('Notes supprimées', 'success');
  } catch (error) {
    console.error('Failed to clear notes:', error);
    utils.showToast(error.message || 'Suppression impossible', 'error');
  }
}

function startUpgradeNotesEdit() {
  if (!currentDevice) return;
  editingUpgradeNotes = true;
  renderDeviceDetails(currentDevice);
}

function cancelUpgradeNotesEdit() {
  editingUpgradeNotes = false;
  renderDeviceDetails(currentDevice);
}

async function saveUpgradeNotes() {
  if (!currentDevice || !currentDevice.last_benchmark) return;
  const textarea = document.getElementById('upgrade-notes-editor');
  const value = textarea ? textarea.value.trim() : '';
  try {
    await apiClient.updateBenchmark(currentDevice.last_benchmark.id, { notes: value || null });
    editingUpgradeNotes = false;
    await reloadCurrentDevice();
    utils.showToast('Upgrade notes sauvegardées', 'success');
  } catch (error) {
    console.error('Failed to save upgrade notes:', error);
    utils.showToast(error.message || 'Échec de la sauvegarde des upgrade notes', 'error');
  }
}

async function clearUpgradeNotes() {
  if (!currentDevice || !currentDevice.last_benchmark) return;
  if (!confirm('Supprimer les upgrade notes ?')) return;
  try {
    await apiClient.updateBenchmark(currentDevice.last_benchmark.id, { notes: null });
    editingUpgradeNotes = false;
    await reloadCurrentDevice();
    utils.showToast('Upgrade notes supprimées', 'success');
  } catch (error) {
    console.error('Failed to clear upgrade notes:', error);
    utils.showToast(error.message || 'Suppression impossible', 'error');
  }
}

function startPurchaseEdit() {
  if (!currentDevice) return;
  editingPurchase = true;
  renderDeviceDetails(currentDevice);
}

function cancelPurchaseEdit() {
  editingPurchase = false;
  renderDeviceDetails(currentDevice);
}

async function savePurchaseInfo() {
  if (!currentDevice) return;
  const storeInput = document.getElementById('purchase-store-input');
  const dateInput = document.getElementById('purchase-date-input');
  const priceInput = document.getElementById('purchase-price-input');

  const store = storeInput ? storeInput.value.trim() : '';
  const date = dateInput ? dateInput.value.trim() : '';
  const priceValue = priceInput ? priceInput.value.trim() : '';
  const price = priceValue !== '' && !Number.isNaN(Number(priceValue)) ? Number(priceValue) : null;

  try {
    await apiClient.updateDevice(currentDevice.id, {
      purchase_store: store || null,
      purchase_date: date || null,
      purchase_price: price
    });
    editingPurchase = false;
    await reloadCurrentDevice();
    utils.showToast('Informations d’achat mises à jour', 'success');
  } catch (error) {
    console.error('Failed to save purchase info:', error);
    utils.showToast(error.message || 'Échec de la sauvegarde', 'error');
  }
}

async function addTag() {
  if (!currentDevice) return;
  const input = document.getElementById(`new-tag-input-${currentDevice.id}`);
  if (!input) return;
  const value = input.value.trim();
  if (!value) return;

  const tags = utils.parseTags(currentDevice.tags);
  if (tags.includes(value)) {
    utils.showToast('Tag déjà présent', 'warning');
    return;
  }

  tags.push(value);
  try {
    await apiClient.updateDevice(currentDevice.id, { tags: tags.join(',') });
    input.value = '';
    await reloadCurrentDevice();
  } catch (error) {
    console.error('Failed to add tag:', error);
    utils.showToast(error.message || 'Ajout impossible', 'error');
  }
}

async function removeTag(tagValue) {
  if (!currentDevice) return;
  const tags = utils.parseTags(currentDevice.tags).filter(tag => tag !== tagValue);
  try {
    await apiClient.updateDevice(currentDevice.id, { tags: tags.length ? tags.join(',') : null });
    await reloadCurrentDevice();
  } catch (error) {
    console.error('Failed to remove tag:', error);
    utils.showToast(error.message || 'Suppression du tag impossible', 'error');
  }
}

async function addDeviceLinkEntry(deviceId) {
  const labelInput = document.getElementById(`link-label-${deviceId}`);
  const urlInput = document.getElementById(`link-url-${deviceId}`);
  if (!labelInput || !urlInput) return;

  const label = labelInput.value.trim();
  const url = urlInput.value.trim();

  if (!label || !url) {
    utils.showToast('Libellé et URL requis', 'warning');
    return;
  }

  try {
    await apiClient.addDeviceLink(deviceId, { label, url });
    labelInput.value = '';
    urlInput.value = '';
    utils.showToast('Lien ajouté', 'success');
    loadLinksSection(deviceId);
  } catch (error) {
    console.error('Failed to add link:', error);
    utils.showToast(error.message || 'Ajout du lien impossible', 'error');
  }
}

async function deleteDeviceLink(linkId, deviceId) {
  if (!confirm('Supprimer ce lien ?')) return;
  try {
    await apiClient.deleteLink(linkId);
    utils.showToast('Lien supprimé', 'success');
    loadLinksSection(deviceId);
  } catch (error) {
    console.error('Failed to delete link:', error);
    utils.showToast(error.message || 'Suppression impossible', 'error');
  }
}

// Upload image for device
async function uploadImage() {
  if (!currentDevice) return;

  const input = document.createElement('input');
  input.type = 'file';
  input.accept = 'image/*';

  input.onchange = async (e) => {
    const file = e.target.files[0];
    if (!file) return;

    // Check file size (max 10MB)
    if (file.size > 10 * 1024 * 1024) {
      alert('L\'image est trop volumineuse (max 10MB)');
      return;
    }

    try {
      console.log('📤 Uploading image:', file.name);

      await apiClient.uploadDocument(currentDevice.id, file, 'image');

      console.log('✅ Image uploaded successfully');

      // Reload device data to show the new image
      const updatedDevice = await apiClient.getDevice(currentDevice.id);
      currentDevice = updatedDevice;
      renderDeviceDetails(updatedDevice);

    } catch (error) {
      console.error('❌ Failed to upload image:', error);
      alert('Erreur lors du chargement de l\'image: ' + (error.message || 'Erreur inconnue'));
    }
  };

  input.click();
}

// Upload PDF for device
async function uploadPDF() {
  if (!currentDevice) return;

  const input = document.createElement('input');
  input.type = 'file';
  input.accept = 'application/pdf';

  input.onchange = async (e) => {
    const file = e.target.files[0];
    if (!file) return;

    // Check file size (max 50MB)
    if (file.size > 50 * 1024 * 1024) {
      alert('Le PDF est trop volumineux (max 50MB)');
      return;
    }

    try {
      console.log('📤 Uploading PDF:', file.name);

      await apiClient.uploadDocument(currentDevice.id, file, 'manual');

      console.log('✅ PDF uploaded successfully');

      // Reload device data to show the new PDF
      const updatedDevice = await apiClient.getDevice(currentDevice.id);
      currentDevice = updatedDevice;
      renderDeviceDetails(updatedDevice);

    } catch (error) {
      console.error('❌ Failed to upload PDF:', error);
      alert('Erreur lors du chargement du PDF: ' + (error.message || 'Erreur inconnue'));
    }
  };

  input.click();
}

// Delete document
async function deleteDocument(docId) {
  if (!currentDevice) return;

  if (!confirm('Voulez-vous vraiment supprimer ce document ?')) {
    return;
  }

  try {
    console.log('🗑️ Deleting document:', docId);

    await apiClient.deleteDocument(docId);

    console.log('✅ Document deleted successfully');

    // Reload device data
    const updatedDevice = await apiClient.getDevice(currentDevice.id);
    currentDevice = updatedDevice;
    renderDeviceDetails(updatedDevice);

  } catch (error) {
    console.error('❌ Failed to delete document:', error);
    alert('Erreur lors de la suppression: ' + (error.message || 'Erreur inconnue'));
  }
}

// Helper: Render image documents
function renderImageDocuments(documents) {
  if (!documents || !Array.isArray(documents)) {
    return '<span>🖼️ Aucune image</span>';
  }

  const imageDocs = documents.filter(doc => doc.doc_type === 'image');

  if (imageDocs.length === 0) {
    return '<span>🖼️ Aucune image</span>';
  }

  return `
    <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 0.75rem; width: 100%;">
      ${imageDocs.map(imageDoc => {
        const downloadUrl = apiClient.getDocumentDownloadUrl(imageDoc.id);
        const safeFilenameArg = utils.escapeHtml(JSON.stringify(imageDoc.filename || ''));
        return `
          <div style="position: relative; border: 1px solid var(--border-color); border-radius: 6px; overflow: hidden; background: var(--bg-primary);">
            <img
              src="${downloadUrl}"
              alt="${utils.escapeHtml(imageDoc.filename)}"
              style="width: 100%; height: 150px; object-fit: cover; cursor: pointer;"
              onclick="previewImage(${imageDoc.id}, ${safeFilenameArg})"
              title="Prévisualiser"
            >
            <div style="padding: 0.5rem; display: flex; justify-content: space-between; align-items: center; background: var(--bg-secondary);">
              <div style="font-size: 0.75rem; color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;" title="${utils.escapeHtml(imageDoc.filename)}">
                📎 ${utils.escapeHtml(imageDoc.filename.substring(0, 15))}${imageDoc.filename.length > 15 ? '...' : ''}
              </div>
              <button onclick="event.stopPropagation(); deleteDocument(${imageDoc.id})" class="icon-btn danger" title="Supprimer" type="button">
                <img src="icons/icons8-delete-48.png" alt="Supprimer">
              </button>
            </div>
          </div>
        `;
      }).join('')}
    </div>
  `;
}

// Helper: Render PDF documents
function renderPDFDocuments(documents) {
  if (!documents || !Array.isArray(documents)) {
    return '<span>📄 Aucun PDF</span>';
  }

  const pdfDocs = documents.filter(doc => doc.doc_type === 'manual');

  if (pdfDocs.length === 0) {
    return '<span>📄 Aucun PDF</span>';
  }

  return pdfDocs.map(doc => {
    const downloadUrl = apiClient.getDocumentDownloadUrl(doc.id);
    const uploadDate = new Date(doc.uploaded_at).toLocaleDateString('fr-FR');

    return `
      <div style="width: 100%; background: var(--bg-secondary); padding: 0.75rem; border-radius: 6px; margin-bottom: 0.5rem; border: 1px solid var(--border-color);">
        <div style="display: flex; justify-content: space-between; align-items: center;">
          <div style="flex: 1;">
            <div style="font-weight: 600; color: var(--text-primary); margin-bottom: 0.25rem;">
              📄 ${utils.escapeHtml(doc.filename)}
            </div>
            <div style="font-size: 0.8rem; color: var(--text-secondary);">
              Uploadé le ${uploadDate}
            </div>
          </div>
          <div class="doc-actions">
            <button onclick="previewPDF(${doc.id}, ${utils.escapeHtml(JSON.stringify(doc.filename || ''))})" class="icon-btn" title="Prévisualiser" type="button">
              <img src="icons/icons8-picture-48.png" alt="Preview">
            </button>
            <a href="${downloadUrl}" download class="icon-btn" title="Télécharger">
              <img src="icons/icons8-save-48.png" alt="Télécharger">
            </a>
            <button onclick="deleteDocument(${doc.id})" class="icon-btn danger" title="Supprimer" type="button">
              <img src="icons/icons8-delete-48.png" alt="Supprimer">
            </button>
          </div>
        </div>
      </div>
    `;
  }).join('');
}

// Helper: Render Motherboard Details
function renderMotherboardDetails(snapshot) {
  if (!snapshot) {
    return '<p style="color: var(--text-muted); text-align: center; padding: 2rem;">Aucune information disponible</p>';
  }

  const cleanValue = (val) => {
    if (!val || (typeof val === 'string' && val.trim() === '')) return 'N/A';
    return val;
  };

  const items = [
    { label: 'Fabricant', value: cleanValue(snapshot.motherboard_vendor) },
    { label: 'Modèle', value: cleanValue(snapshot.motherboard_model) },
    { label: 'BIOS Vendor', value: cleanValue(snapshot.bios_vendor) },
    { label: 'Version BIOS', value: cleanValue(snapshot.bios_version) },
    { label: 'Date BIOS', value: cleanValue(snapshot.bios_date) },
    { label: 'Slots RAM', value: `${snapshot.ram_slots_used || '?'} utilisés / ${snapshot.ram_slots_total || '?'} total` }
  ];

  return `
    <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 0.75rem;">
      ${items.map(item => `
        <div style="padding: 0.75rem; background: var(--bg-primary); border-radius: 6px; border: 1px solid var(--border-color);">
          <div style="font-size: 0.8rem; color: var(--text-secondary); margin-bottom: 0.25rem;">${item.label}</div>
          <div style="font-weight: 600; color: var(--text-primary);">${utils.escapeHtml(String(item.value))}</div>
        </div>
      `).join('')}
    </div>
  `;
}

// Helper: Render CPU Details
function renderCPUDetails(snapshot) {
  if (!snapshot) {
    return '<p style="color: var(--text-muted); text-align: center; padding: 2rem;">Aucune information disponible</p>';
  }

  const items = [
    { label: 'Fabricant', value: snapshot.cpu_vendor || 'N/A', tooltip: snapshot.cpu_model },
    { label: 'Modèle', value: snapshot.cpu_model || 'N/A', tooltip: snapshot.cpu_microarchitecture ? `Architecture: ${snapshot.cpu_microarchitecture}` : null },
    { label: 'Microarchitecture', value: snapshot.cpu_microarchitecture || 'N/A' },
    { label: 'Cores', value: snapshot.cpu_cores != null ? snapshot.cpu_cores : 'N/A', tooltip: snapshot.cpu_threads ? `${snapshot.cpu_threads} threads disponibles` : null },
    { label: 'Threads', value: snapshot.cpu_threads != null ? snapshot.cpu_threads : 'N/A', tooltip: snapshot.cpu_cores ? `${snapshot.cpu_cores} cores physiques` : null },
    { label: 'Fréquence de base', value: snapshot.cpu_base_freq_ghz ? `${snapshot.cpu_base_freq_ghz} GHz` : 'N/A', tooltip: snapshot.cpu_max_freq_ghz ? `Max: ${snapshot.cpu_max_freq_ghz} GHz` : null },
    { label: 'Fréquence max', value: snapshot.cpu_max_freq_ghz ? `${snapshot.cpu_max_freq_ghz} GHz` : 'N/A', tooltip: snapshot.cpu_base_freq_ghz ? `Base: ${snapshot.cpu_base_freq_ghz} GHz` : null },
    { label: 'TDP', value: snapshot.cpu_tdp_w ? `${snapshot.cpu_tdp_w} W` : 'N/A', tooltip: 'Thermal Design Power - Consommation thermique typique' },
    { label: 'Cache L1', value: snapshot.cpu_cache_l1_kb ? utils.formatCache(snapshot.cpu_cache_l1_kb) : 'N/A', tooltip: 'Cache de niveau 1 - Le plus rapide' },
    { label: 'Cache L2', value: snapshot.cpu_cache_l2_kb ? utils.formatCache(snapshot.cpu_cache_l2_kb) : 'N/A', tooltip: 'Cache de niveau 2 - Intermédiaire' },
    { label: 'Cache L3', value: snapshot.cpu_cache_l3_kb ? utils.formatCache(snapshot.cpu_cache_l3_kb) : 'N/A', tooltip: 'Cache de niveau 3 - Partagé entre les cores' }
  ];

  let html = `
    <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 0.75rem;">
      ${items.map(item => `
        <div style="padding: 0.75rem; background: var(--bg-primary); border-radius: 6px; border: 1px solid var(--border-color);" ${item.tooltip ? `class="tooltip" data-tooltip="${utils.escapeHtml(item.tooltip)}"` : ''}>
          <div style="font-size: 0.8rem; color: var(--text-secondary); margin-bottom: 0.25rem;">${item.label}</div>
          <div style="font-weight: 600; color: var(--text-primary); font-size: 0.95rem;">${utils.escapeHtml(String(item.value))}</div>
        </div>
      `).join('')}
    </div>
  `;

  // CPU Flags
  if (snapshot.cpu_flags) {
    try {
      const flags = typeof snapshot.cpu_flags === 'string' ? JSON.parse(snapshot.cpu_flags) : snapshot.cpu_flags;
      if (Array.isArray(flags) && flags.length > 0) {
        html += `
          <div style="margin-top: 1rem; padding: 1rem; background: var(--bg-primary); border-radius: 6px; border: 1px solid var(--border-color);">
            <div style="font-weight: 600; margin-bottom: 0.5rem; color: var(--text-secondary);">Instructions supportées:</div>
            <div style="display: flex; flex-wrap: wrap; gap: 0.5rem;">
              ${flags.slice(0, 30).map(flag => `<span class="badge badge-muted" style="font-size: 0.75rem;">${utils.escapeHtml(flag)}</span>`).join('')}
              ${flags.length > 30 ? `<span class="badge">+${flags.length - 30} autres...</span>` : ''}
            </div>
          </div>
        `;
      }
    } catch (e) {
      console.warn('Failed to parse CPU flags:', e);
    }
  }

  return html;
}

// Helper: Render Memory Details
function renderMemoryDetails(snapshot) {
  if (!snapshot) {
    return '<p style="color: var(--text-muted); text-align: center; padding: 2rem;">Aucune information disponible</p>';
  }

  const items = [
    { label: 'RAM totale', value: snapshot.ram_total_mb ? utils.formatMemory(snapshot.ram_total_mb) : 'N/A' },
    { label: 'RAM utilisée', value: snapshot.ram_used_mb ? utils.formatMemory(snapshot.ram_used_mb) : 'N/A' },
    { label: 'RAM libre', value: snapshot.ram_free_mb ? utils.formatMemory(snapshot.ram_free_mb) : 'N/A' },
    { label: 'RAM partagée', value: snapshot.ram_shared_mb ? utils.formatMemory(snapshot.ram_shared_mb) : 'N/A' },
    { label: 'Slots utilisés', value: snapshot.ram_slots_used != null ? snapshot.ram_slots_used : 'N/A' },
    { label: 'Slots total', value: snapshot.ram_slots_total != null ? snapshot.ram_slots_total : 'N/A' },
    { label: 'ECC', value: snapshot.ram_ecc != null ? (snapshot.ram_ecc ? 'Oui' : 'Non') : 'N/A' }
  ];

  let html = `
    <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 0.75rem;">
      ${items.map(item => `
        <div style="padding: 0.75rem; background: var(--bg-primary); border-radius: 6px; border: 1px solid var(--border-color);">
          <div style="font-size: 0.8rem; color: var(--text-secondary); margin-bottom: 0.25rem;">${item.label}</div>
          <div style="font-weight: 600; color: var(--text-primary); font-size: 0.95rem;">${utils.escapeHtml(String(item.value))}</div>
        </div>
      `).join('')}
    </div>
  `;

  // RAM Layout (if available)
  if (snapshot.ram_layout_json) {
    try {
      const layout = typeof snapshot.ram_layout_json === 'string' ? JSON.parse(snapshot.ram_layout_json) : snapshot.ram_layout_json;
      if (Array.isArray(layout) && layout.length > 0) {
        html += `
          <div style="margin-top: 1rem; padding: 1rem; background: var(--bg-primary); border-radius: 6px; border: 1px solid var(--border-color);">
            <div style="font-weight: 600; margin-bottom: 0.5rem; color: var(--text-secondary);">Configuration des barrettes:</div>
            <div style="display: grid; gap: 0.5rem;">
              ${layout.map(slot => `
                <div style="padding: 0.5rem; background: var(--bg-secondary); border-radius: 4px; font-size: 0.85rem;">
                  <strong>${utils.escapeHtml(slot.slot || 'N/A')}</strong>:
                  ${utils.formatMemory(slot.size_mb || 0)}
                  ${slot.type ? `(${utils.escapeHtml(slot.type)})` : ''}
                  ${slot.speed_mhz ? `@ ${slot.speed_mhz} MHz` : ''}
                </div>
              `).join('')}
            </div>
          </div>
        `;
      }
    } catch (e) {
      console.warn('Failed to parse RAM layout:', e);
    }
  }

  return html;
}

// Helper: Render Storage Details
function renderStorageDetails(snapshot) {
  if (!snapshot) {
    return '<p style="color: var(--text-muted); text-align: center; padding: 2rem;">Aucune information disponible</p>';
  }

  let html = '';

  try {
    if (snapshot.storage_devices_json) {
      const devices = typeof snapshot.storage_devices_json === 'string'
        ? JSON.parse(snapshot.storage_devices_json)
        : snapshot.storage_devices_json;

      if (Array.isArray(devices) && devices.length > 0) {
        html += `
          <div style="display: grid; gap: 0.75rem;">
            ${devices.map(disk => {
              const typeIcon = disk.type === 'SSD' ? '💾' : '💿';
              const healthColor = disk.smart_health === 'PASSED' ? 'var(--color-success)' :
                                disk.smart_health === 'FAILED' ? 'var(--color-danger)' :
                                'var(--text-secondary)';

              return `
                <div style="border: 1px solid var(--border-color); border-radius: 8px; padding: 1rem; background: var(--bg-primary);">
                  <div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 0.5rem;">
                    <div>
                      <div style="font-weight: 600; color: var(--color-primary);">
                        ${typeIcon} ${utils.escapeHtml(disk.name || disk.device || 'N/A')}
                      </div>
                      <div style="color: var(--text-secondary); font-size: 0.85rem; margin-top: 0.25rem;">
                        ${utils.escapeHtml(disk.model || 'Unknown model')}
                      </div>
                    </div>
                    ${disk.smart_health ? `
                      <span class="badge" style="background: ${healthColor}; color: white; font-size: 0.75rem;">
                        ${utils.escapeHtml(disk.smart_health)}
                      </span>
                    ` : ''}
                  </div>
                  <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 0.5rem; font-size: 0.85rem; color: var(--text-secondary);">
                    ${disk.capacity_gb ? `<div><strong>Capacité:</strong> ${utils.formatStorage(disk.capacity_gb)}</div>` : ''}
                    ${disk.type ? `<div><strong>Type:</strong> ${utils.escapeHtml(disk.type)}</div>` : ''}
                    ${disk.interface ? `<div><strong>Interface:</strong> ${utils.escapeHtml(disk.interface)}</div>` : ''}
                    ${disk.temperature_c ? `<div><strong>Température:</strong> ${utils.formatTemperature(disk.temperature_c)}</div>` : ''}
                  </div>
                </div>
              `;
            }).join('')}
          </div>
        `;
      } else {
        html += '<p style="color: var(--text-muted); text-align: center; padding: 2rem;">Aucun disque détecté</p>';
      }
    }
  } catch (e) {
    console.error('Failed to parse storage devices:', e);
    html += '<p style="color: var(--color-danger); text-align: center; padding: 2rem;">Erreur lors du parsing des données de stockage</p>';
  }

  if (snapshot.partitions_json) {
    try {
      const partitions = typeof snapshot.partitions_json === 'string'
        ? JSON.parse(snapshot.partitions_json)
        : snapshot.partitions_json;

      if (Array.isArray(partitions) && partitions.length > 0) {
        html += `
          <div style="margin-top: 1.5rem;">
            <h4 style="margin-bottom: 0.5rem; color: var(--text-secondary);">Partitions</h4>
            <div style="overflow-x: auto;">
              <table style="width: 100%; border-collapse: collapse;">
                <thead>
                  <tr style="border-bottom: 1px solid var(--border-color); color: var(--text-secondary); text-align: left;">
                    <th style="padding: 0.5rem;">Partition</th>
                    <th style="padding: 0.5rem;">Montage</th>
                    <th style="padding: 0.5rem;">Type</th>
                    <th style="padding: 0.5rem;">Utilisé</th>
                    <th style="padding: 0.5rem;">Libre</th>
                    <th style="padding: 0.5rem;">Total</th>
                    <th style="padding: 0.5rem;">Usage</th>
                  </tr>
                </thead>
                <tbody>
                  ${partitions.map(part => {
                    const used = typeof part.used_gb === 'number' ? utils.formatStorage(part.used_gb) : 'N/A';
                    const free = typeof part.free_gb === 'number'
                      ? utils.formatStorage(part.free_gb)
                      : (typeof part.total_gb === 'number' && typeof part.used_gb === 'number'
                          ? utils.formatStorage(part.total_gb - part.used_gb)
                          : 'N/A');
                    const total = typeof part.total_gb === 'number' ? utils.formatStorage(part.total_gb) : 'N/A';

                    return `
                      <tr style="border-bottom: 1px solid var(--border-color);">
                        <td style="padding: 0.5rem; font-weight: 600;">${utils.escapeHtml(part.name || 'N/A')}</td>
                        <td style="padding: 0.5rem;">${part.mount_point ? utils.escapeHtml(part.mount_point) : '<span style="color: var(--text-muted);">Non monté</span>'}</td>
                        <td style="padding: 0.5rem;">${part.fs_type ? utils.escapeHtml(part.fs_type) : 'N/A'}</td>
                        <td style="padding: 0.5rem;">${used}</td>
                        <td style="padding: 0.5rem;">${free}</td>
                        <td style="padding: 0.5rem;">${total}</td>
                        <td style="padding: 0.5rem;">${renderUsageBadge(part.used_gb, part.total_gb)}</td>
                      </tr>
                    `;
                  }).join('')}
                </tbody>
              </table>
            </div>
          </div>
        `;
      }
    } catch (error) {
      console.error('Failed to parse partitions:', error);
      html += '<p style="color: var(--color-danger); text-align: center; padding: 1rem;">Erreur lors de la lecture des partitions</p>';
    }
  }

  if (!html) {
    html = '<p style="color: var(--text-muted); text-align: center; padding: 2rem;">Aucune information disponible</p>';
  }

  return html;
}

// Helper: Render GPU Details
function renderGPUDetails(snapshot) {
  if (!snapshot) {
    return '<p style="color: var(--text-muted); text-align: center; padding: 2rem;">Aucune information disponible</p>';
  }

  if (!snapshot.gpu_vendor && !snapshot.gpu_model && !snapshot.gpu_summary) {
    return '<p style="color: var(--text-muted); text-align: center; padding: 2rem;">Aucun GPU détecté</p>';
  }

  const items = [
    { label: 'Fabricant', value: snapshot.gpu_vendor || 'N/A' },
    { label: 'Modèle', value: snapshot.gpu_model || snapshot.gpu_summary || 'N/A' }
  ];

  return `
    <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 0.75rem;">
      ${items.map(item => `
        <div style="padding: 0.75rem; background: var(--bg-primary); border-radius: 6px; border: 1px solid var(--border-color);">
          <div style="font-size: 0.8rem; color: var(--text-secondary); margin-bottom: 0.25rem;">${item.label}</div>
          <div style="font-weight: 600; color: var(--text-primary);">${utils.escapeHtml(String(item.value))}</div>
        </div>
      `).join('')}
    </div>
  `;
}

// Helper: Render OS Details
function renderOSDetails(snapshot) {
  if (!snapshot) {
    return '<p style="color: var(--text-muted); text-align: center; padding: 2rem;">Aucune information disponible</p>';
  }

  const displayServer = snapshot.display_server || snapshot.session_type || 'N/A';
  const resolution = snapshot.screen_resolution || 'N/A';
  const lastBoot = snapshot.last_boot_time || 'N/A';
  const uptime = snapshot.uptime_seconds != null ? utils.formatDuration(snapshot.uptime_seconds) : 'N/A';
  const battery = snapshot.battery_percentage != null
    ? `${snapshot.battery_percentage}%${snapshot.battery_status ? ` (${snapshot.battery_status})` : ''}`
    : 'N/A';

  const items = [
    { label: 'Hostname', value: snapshot.hostname || 'N/A' },
    { label: 'Distribution', value: snapshot.os_name || 'N/A' },
    { label: 'Version', value: snapshot.os_version || 'N/A' },
    { label: 'Kernel', value: snapshot.kernel_version || 'N/A' },
    { label: 'Architecture', value: snapshot.architecture || 'N/A' },
    { label: 'Environnement', value: snapshot.desktop_environment || 'N/A' },
    { label: 'Session / Display', value: displayServer },
    { label: 'Résolution écran', value: resolution },
    { label: 'Dernier boot', value: lastBoot },
    { label: 'Uptime', value: uptime },
    { label: 'Batterie', value: battery },
    { label: 'Virtualisation', value: snapshot.virtualization_type || 'none' }
  ];

  return `
    <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 0.75rem;">
      ${items.map(item => `
        <div style="padding: 0.75rem; background: var(--bg-primary); border-radius: 6px; border: 1px solid var(--border-color);">
          <div style="font-size: 0.8rem; color: var(--text-secondary); margin-bottom: 0.25rem;">${item.label}</div>
          <div style="font-weight: 600; color: var(--text-primary);">${utils.escapeHtml(String(item.value))}</div>
        </div>
      `).join('')}
    </div>
  `;
}

// Helper: Render PCI Devices
function renderPCIDetails(snapshot) {
  if (!snapshot || !snapshot.pci_devices_json) {
    return '<p style="color: var(--text-muted); text-align: center; padding: 2rem;">Aucune information disponible</p>';
  }

  try {
    const devices = typeof snapshot.pci_devices_json === 'string'
      ? JSON.parse(snapshot.pci_devices_json)
      : snapshot.pci_devices_json;

    if (!Array.isArray(devices) || devices.length === 0) {
      return '<p style="color: var(--text-muted); text-align: center; padding: 2rem;">Aucun périphérique PCI détecté</p>';
    }

    return `
      <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.5rem; max-height: 400px; overflow-y: auto;">
        ${devices.map(dev => `
          <div style="border: 1px solid var(--border-color); border-radius: 6px; padding: 0.75rem; background: var(--bg-primary);">
            <div style="display: grid; grid-template-columns: 100px 1fr; gap: 0.5rem; font-size: 0.85rem;">
              <div style="color: var(--text-secondary);">Slot:</div>
              <div style="font-weight: 600; color: var(--color-primary);">${utils.escapeHtml(dev.slot || 'N/A')}</div>

              <div style="color: var(--text-secondary);">Class:</div>
              <div>${utils.escapeHtml(dev.class || 'N/A')}</div>

              <div style="color: var(--text-secondary);">Vendor:</div>
              <div>${utils.escapeHtml(dev.vendor || 'N/A')}</div>

              <div style="color: var(--text-secondary);">Device:</div>
              <div>${utils.escapeHtml(dev.device || 'N/A')}</div>
            </div>
          </div>
        `).join('')}
      </div>
    `;
  } catch (e) {
    console.error('Failed to parse PCI devices:', e);
    return '<p style="color: var(--color-danger); text-align: center; padding: 2rem;">Erreur lors du parsing des données PCI</p>';
  }
}

// Helper: Render USB Devices
function renderUSBDetails(snapshot) {
  if (!snapshot || !snapshot.usb_devices_json) {
    return '<p style="color: var(--text-muted); text-align: center; padding: 2rem;">Aucune information disponible</p>';
  }

  try {
    const devices = typeof snapshot.usb_devices_json === 'string'
      ? JSON.parse(snapshot.usb_devices_json)
      : snapshot.usb_devices_json;

    if (!Array.isArray(devices) || devices.length === 0) {
      return '<p style="color: var(--text-muted); text-align: center; padding: 2rem;">Aucun périphérique USB détecté</p>';
    }

    return `
      <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.5rem; max-height: 400px; overflow-y: auto;">
        ${devices.map(dev => `
          <div style="border: 1px solid var(--border-color); border-radius: 6px; padding: 0.75rem; background: var(--bg-primary);">
            <div style="font-weight: 600; color: var(--color-primary); margin-bottom: 0.5rem;">
              ${utils.escapeHtml(dev.name || 'Unknown USB Device')}
            </div>
            <div style="display: grid; grid-template-columns: 120px 1fr; gap: 0.5rem; font-size: 0.85rem; color: var(--text-secondary);">
              <div>Bus/Device:</div>
              <div>${utils.escapeHtml(dev.bus || 'N/A')} / ${utils.escapeHtml(dev.device || 'N/A')}</div>

              <div>Vendor ID:</div>
              <div>${utils.escapeHtml(dev.vendor_id || 'N/A')}</div>

              <div>Product ID:</div>
              <div>${utils.escapeHtml(dev.product_id || 'N/A')}</div>
            </div>
          </div>
        `).join('')}
      </div>
    `;
  } catch (e) {
    console.error('Failed to parse USB devices:', e);
    return '<p style="color: var(--color-danger); text-align: center; padding: 2rem;">Erreur lors du parsing des données USB</p>';
  }
}

// Helper: View benchmark details
async function viewBenchmarkDetails(benchmarkId) {
  const modalBody = document.getElementById('benchmarkModalBody');
  utils.openModal('benchmarkModal');

  try {
    const benchmark = await apiClient.getBenchmark(benchmarkId);

    modalBody.innerHTML = `
      <div style="max-height: 500px; overflow-y: auto; background: var(--bg-primary); padding: 1rem; border-radius: 6px;">
        <pre style="margin: 0; white-space: pre-wrap; word-wrap: break-word; font-size: 0.85rem; color: var(--text-primary);"><code>${JSON.stringify(benchmark.details || benchmark, null, 2)}</code></pre>
      </div>
    `;

  } catch (error) {
    console.error('Failed to load benchmark details:', error);
    modalBody.innerHTML = `<div style="color: var(--color-danger); padding: 1rem;">Erreur: ${utils.escapeHtml(error.message)}</div>`;
  }
}

// Render IP Display with edit capability
function renderIPDisplay(snapshot, device) {
  // Extract non-loopback IPs
  const networkInterfaces = snapshot?.network_interfaces_json ?
    (typeof snapshot.network_interfaces_json === 'string' ? JSON.parse(snapshot.network_interfaces_json) : snapshot.network_interfaces_json) :
    [];

  const ips = networkInterfaces
    .filter(iface => iface.ipv4 && iface.ipv4 !== '127.0.0.1' && iface.ipv4 !== 'N/A')
    .map(iface => iface.ipv4);

  const displayIP = ips.length > 0 ? ips.join(', ') : 'N/A';
  const ipUrl = device.ip_url || (ips.length > 0 ? `http://${ips[0]}` : '');

  return `
    <div style="display: flex; flex-direction: column; gap: 0.5rem;">
      <div style="display: flex; align-items: center; gap: 0.5rem;">
        ${ipUrl ? `<a href="${utils.escapeHtml(ipUrl)}" target="_blank" rel="noopener noreferrer" style="color: var(--color-info); text-decoration: none; font-weight: 600;" title="Ouvrir ${utils.escapeHtml(ipUrl)}">${utils.escapeHtml(displayIP)}</a>` : `<span>${utils.escapeHtml(displayIP)}</span>`}
        <button id="btn-edit-ip-url" class="icon-btn" data-icon="edit" title="Éditer le lien IP" type="button" style="padding: 0.25rem; font-size: 0.75rem;">
          <span data-icon="edit"></span>
        </button>
      </div>
      <div id="ip-url-editor" style="display: none;">
        <input type="text" id="ip-url-input" class="ip-url-input" placeholder="http://${ips[0] || '10.0.0.1'}" value="${utils.escapeHtml(ipUrl)}" style="width: 100%; padding: 0.5rem; border: 1px solid var(--border-color); border-radius: 4px; background: var(--bg-primary); color: var(--text-primary);">
        <div style="display: flex; gap: 0.5rem; margin-top: 0.5rem;">
          <button id="btn-save-ip-url" class="btn btn-success btn-sm" data-icon="check" type="button">
            <span data-icon="check"></span> Sauvegarder
          </button>
          <button id="btn-cancel-ip-url" class="btn btn-secondary btn-sm" data-icon="times" type="button">
            <span data-icon="times"></span> Annuler
          </button>
        </div>
      </div>
    </div>
  `;
}

async function editIPUrl() {
  const editor = document.getElementById('ip-url-editor');
  const btnEdit = document.getElementById('btn-edit-ip-url');
  if (!editor || !btnEdit) return;

  editor.style.display = 'block';
  btnEdit.style.display = 'none';
  document.getElementById('ip-url-input')?.focus();
}

async function saveIPUrl() {
  if (!currentDevice) return;

  const input = document.getElementById('ip-url-input');
  if (!input) return;

  let url = input.value.trim();

  // Auto-prefix http:// if not present and not empty
  if (url && !url.match(/^https?:\/\//)) {
    url = `http://${url}`;
  }

  try {
    await apiClient.updateDevice(currentDevice.id, { ip_url: url || null });
    utils.showToast('Lien IP sauvegardé', 'success');
    await reloadCurrentDevice();
  } catch (error) {
    console.error('Failed to save IP URL:', error);
    utils.showToast(error.message || 'Échec de la sauvegarde du lien IP', 'error');
  }
}

async function cancelIPUrlEdit() {
  if (!currentDevice) return;

  const editor = document.getElementById('ip-url-editor');
  const btnEdit = document.getElementById('btn-edit-ip-url');
  if (!editor || !btnEdit) return;

  editor.style.display = 'none';
  btnEdit.style.display = 'inline-block';

  // Reset input value
  const input = document.getElementById('ip-url-input');
  if (input) {
    input.value = currentDevice.ip_url || '';
  }
}

// Search model on web
function searchModelOnWeb() {
  const btn = document.getElementById('btn-search-model');
  if (!btn) return;

  const model = btn.dataset.model;
  if (!model || model === 'N/A') {
    utils.showToast('Aucun modèle à rechercher', 'warning');
    return;
  }

  // Get search engine from settings (default: Google)
  const searchEngine = localStorage.getItem('searchEngine') || 'google';

  const searchUrls = {
    google: `https://www.google.com/search?q=${encodeURIComponent(model)}`,
    duckduckgo: `https://duckduckgo.com/?q=${encodeURIComponent(model)}`,
    bing: `https://www.bing.com/search?q=${encodeURIComponent(model)}`
  };

  const url = searchUrls[searchEngine] || searchUrls.google;
  window.open(url, '_blank', 'noopener,noreferrer');
}

// Render device details (right panel)
function renderDeviceDetails(device) {
  const previousDeviceId = currentDevice?.id;
  currentDevice = device;
  if (previousDeviceId !== device.id) {
    editingNotes = false;
    editingUpgradeNotes = false;
    editingPurchase = false;
  }
  const detailsContainer = document.getElementById('deviceDetailsContainer');
  const snapshot = device.last_hardware_snapshot;
  const bench = device.last_benchmark;

  const metaParts = [];
  if (device.location) metaParts.push(`📍 ${utils.escapeHtml(device.location)}`);
  if (device.owner) metaParts.push(`👤 ${utils.escapeHtml(device.owner)}`);
  if (device.asset_tag) metaParts.push(`🏷️ ${utils.escapeHtml(device.asset_tag)}`);

  const brand = snapshot?.motherboard_vendor || snapshot?.os_name || 'N/A';
  const model = snapshot?.motherboard_model || snapshot?.os_version || 'N/A';
  const imageCount = (device.documents || []).filter(doc => doc.doc_type === 'image').length;

  const imagesContent = renderImageDocuments(device.documents);

  const headerHtml = `
    <div class="device-preamble">
      <div class="preamble-content">
        <div class="preamble-left">
          <div class="header-row">
            <div>
              <div class="header-label">Hostname</div>
              <div class="header-value">${utils.escapeHtml(device.hostname)}</div>
              <div class="header-meta">${metaParts.length > 0 ? metaParts.join(' • ') : 'Aucune métadonnée'}</div>
            </div>
          </div>
          <div class="header-row">
            <div>
              <div class="header-label">Adresse IP</div>
              <div class="header-value" id="ip-display-container">
                ${renderIPDisplay(snapshot, device)}
              </div>
            </div>
          </div>
          <div class="header-row">
            <div>
              <div class="header-label">Marque</div>
              <div class="header-value">${utils.escapeHtml(brand)}</div>
            </div>
          </div>
          <div class="header-row">
            <div>
              <div class="header-label">Modèle</div>
              <div class="header-value" style="display: flex; align-items: center; gap: 0.5rem;">
                <span>${utils.escapeHtml(model)}</span>
                <button id="btn-search-model" class="icon-btn" title="Recherche sur le Web" type="button" style="padding: 0.25rem; font-size: 0.75rem;" data-model="${utils.escapeHtml(model)}">
                  <span data-icon="globe"></span>
                </button>
              </div>
            </div>
          </div>
          <div class="header-row">
            <div class="header-stat">
              <div class="header-label">Score global</div>
              <div class="header-value">${formatScoreValue(bench?.global_score)}</div>
            </div>
          </div>
          <div class="header-row">
            <button id="btn-delete" class="icon-btn danger" title="Supprimer ce device" type="button">
              <img src="icons/icons8-delete-48.png" alt="Supprimer">
            </button>
          </div>
        </div>
        <div class="preamble-right">
          ${createSection(
            'section-images-header',
            getSectionIcon('images', 'Images'),
            'Images',
            imagesContent,
            {
              actionsHtml: `
                <button id="btn-upload-image-header" class="icon-btn" title="Ajouter une image" type="button">
                  <img src="icons/icons8-picture-48.png" alt="Ajouter">
                </button>
              `
            }
          )}
        </div>
      </div>
    </div>
  `;

  const metadataActions = isEditing
    ? `
      <button id="btn-save" class="icon-btn success" title="Sauvegarder" type="button">
        <img src="icons/icons8-save-48.png" alt="Sauvegarder">
      </button>
      <button id="btn-cancel" class="icon-btn" title="Annuler" type="button">
        <img src="icons/icons8-close-48.png" alt="Annuler">
      </button>
    `
    : `
      <button id="btn-edit" class="icon-btn" title="Éditer les métadonnées" type="button">
        <img src="icons/icons8-edit-pencil-48.png" alt="Éditer">
      </button>
    `;
  const notesActions = editingNotes
    ? `
      <button class="icon-btn success" title="Sauvegarder les notes" onclick="saveNotes()" type="button">
        <img src="icons/icons8-save-48.png" alt="Sauvegarder">
      </button>
      <button class="icon-btn" title="Annuler" onclick="cancelNotesEdit()" type="button">
        <img src="icons/icons8-close-48.png" alt="Annuler">
      </button>
    `
    : `
      <button class="icon-btn" title="Éditer les notes" onclick="startNotesEdit()" type="button">
        <img src="icons/icons8-edit-pencil-48.png" alt="Éditer les notes">
      </button>
      ${device.description ? `
        <button class="icon-btn danger" title="Supprimer les notes" onclick="clearNotes()" type="button">
          <img src="icons/icons8-delete-48.png" alt="Supprimer">
        </button>
      ` : ''}
    `;
  const upgradeActions = currentDevice?.last_benchmark
    ? (editingUpgradeNotes
      ? `
        <button class="icon-btn success" title="Sauvegarder" onclick="saveUpgradeNotes()" type="button">
          <img src="icons/icons8-save-48.png" alt="Sauvegarder">
        </button>
        <button class="icon-btn" title="Annuler" onclick="cancelUpgradeNotesEdit()" type="button">
          <img src="icons/icons8-close-48.png" alt="Annuler">
        </button>
      `
      : `
        <button class="icon-btn" title="Éditer les upgrade notes" onclick="startUpgradeNotesEdit()" type="button">
          <img src="icons/icons8-edit-pencil-48.png" alt="Éditer">
        </button>
        ${currentDevice.last_benchmark.notes ? `
          <button class="icon-btn danger" title="Supprimer" onclick="clearUpgradeNotes()" type="button">
            <img src="icons/icons8-delete-48.png" alt="Supprimer">
          </button>
        ` : ''}
      `)
    : '';
  const purchaseActions = editingPurchase
    ? `
      <button class="icon-btn success" title="Sauvegarder" onclick="savePurchaseInfo()" type="button">
        <img src="icons/icons8-save-48.png" alt="Sauvegarder">
      </button>
      <button class="icon-btn" title="Annuler" onclick="cancelPurchaseEdit()" type="button">
        <img src="icons/icons8-close-48.png" alt="Annuler">
      </button>
    `
    : `
      <button class="icon-btn" title="Modifier les informations d'achat" onclick="startPurchaseEdit()" type="button">
        <img src="icons/icons8-edit-pencil-48.png" alt="Éditer">
      </button>
    `;

  const sections = {
    motherboard: createSection('section-motherboard', getSectionIcon('motherboard', 'Carte Mère'), 'Carte Mère', renderMotherboardDetails(snapshot)),
    cpu: createSection('section-cpu', getSectionIcon('cpu', 'Processeur'), 'Processeur (CPU)', renderCPUDetails(snapshot)),
    ram: createSection('section-ram', getSectionIcon('ram', 'Mémoire'), 'Mémoire (RAM)', renderMemoryDetails(snapshot)),
    disks: createSection('section-disks', getSectionIcon('storage', 'Stockage'), 'Stockage (Disques)', renderStorageDetails(snapshot)),
    gpu: createSection('section-gpu', getSectionIcon('gpu', 'Carte Graphique'), 'Carte Graphique (GPU)', renderGPUDetails(snapshot)),
    network: createSection('section-network', getSectionIcon('network', 'Interfaces réseau'), 'Interfaces Réseau', renderNetworkBlock(snapshot, bench)),
    usb: createSection('section-usb', getSectionIcon('usb', 'USB'), 'Périphériques USB', renderUSBDetails(snapshot)),
    pci: createSection('section-pci', getSectionIcon('pci', 'PCI'), 'Périphériques PCI', renderPCIDetails(snapshot)),
    os: createSection('section-os', getSectionIcon('os', 'Système'), 'Système d’exploitation', renderOSDetails(snapshot)),
    shares: createSection('section-shares', getSectionIcon('shares', 'Partages réseau'), 'Partages réseau', renderNetworkSharesDetails(snapshot)),
    benchmarks: createSection('section-benchmarks', getSectionIcon('benchmarks', 'Benchmarks'), 'Benchmarks', renderBenchmarkSection(device.id, bench)),
    metadata: createSection('section-metadata', getSectionIcon('metadata', 'Métadonnées'), 'Métadonnées', renderMetadataSection(device, bench), { actionsHtml: metadataActions })
  };

  const pdfContent = renderPDFDocuments(device.documents);
  sections.pdf = createSection(
    'section-pdf',
    getSectionIcon('pdf', 'Notices PDF'),
    'Notices PDF',
    pdfContent,
    {
      actionsHtml: `
        <button id="btn-upload-pdf" class="icon-btn" title="Ajouter un PDF" type="button">
          <img src="icons/icons8-bios-94.png" alt="Ajouter un PDF">
        </button>
      `
    }
  );

  sections.links = createSection('section-links', getSectionIcon('links', 'Liens'), 'URLs & Liens', renderLinksPlaceholder(device.id));
  sections.tags = createSection('section-tags', getSectionIcon('tags', 'Tags'), 'Tags', renderTagsSection(device));
  sections.notes = createSection('section-notes', getSectionIcon('notes', 'Notes'), 'Notes (Markdown)', renderNotesSection(device), { actionsHtml: notesActions });
  sections.purchase = createSection('section-purchase', getSectionIcon('purchase', 'Informations d’achat'), 'Informations d’achat', renderPurchaseSection(device), { actionsHtml: purchaseActions });
  sections.upgrades = createSection('section-upgrades', getSectionIcon('upgrade', 'Upgrade Notes'), 'Upgrade Notes', renderUpgradeSection(bench), { actionsHtml: upgradeActions });

  const sectionsOrder = [
    'motherboard',
    'cpu',
    'ram',
    'disks',
    'gpu',
    'network',
    'os',
    'shares',
    'usb',
    'pci',
    'benchmarks',
    'metadata',
    'pdf',
    'links',
    'tags',
    'notes',
    'purchase',
    'upgrades'
  ];

  const orderedSections = sectionsOrder.map(key => sections[key] || '').join('');

  detailsContainer.innerHTML = headerHtml + orderedSections;

  // Initialize icons using IconManager
  if (window.IconManager) {
    window.IconManager.inlineSvgIcons(detailsContainer);
  }

  bindDetailActions();
  loadLinksSection(device.id);
  loadBenchmarkHistorySection(device.id);
}

function bindDetailActions() {
  const btnEdit = document.getElementById('btn-edit');
  const btnSave = document.getElementById('btn-save');
  const btnCancel = document.getElementById('btn-cancel');
  const btnUploadImage = document.getElementById('btn-upload-image');
  const btnUploadImageHeader = document.getElementById('btn-upload-image-header');
  const btnUploadPDF = document.getElementById('btn-upload-pdf');
  const btnDelete = document.getElementById('btn-delete');

  // IP URL editing
  const btnEditIpUrl = document.getElementById('btn-edit-ip-url');
  const btnSaveIpUrl = document.getElementById('btn-save-ip-url');
  const btnCancelIpUrl = document.getElementById('btn-cancel-ip-url');

  // Web search
  const btnSearchModel = document.getElementById('btn-search-model');

  if (btnEdit) btnEdit.addEventListener('click', toggleEditMode);
  if (btnSave) btnSave.addEventListener('click', saveDevice);
  if (btnCancel) {
    btnCancel.addEventListener('click', () => {
      isEditing = false;
      renderDeviceDetails(currentDevice);
    });
  }
  if (btnUploadImage) btnUploadImage.addEventListener('click', uploadImage);
  if (btnUploadImageHeader) btnUploadImageHeader.addEventListener('click', uploadImage);
  if (btnUploadPDF) btnUploadPDF.addEventListener('click', uploadPDF);
  if (btnDelete) btnDelete.addEventListener('click', deleteCurrentDevice);

  // Bind IP URL actions
  if (btnEditIpUrl) btnEditIpUrl.addEventListener('click', editIPUrl);
  if (btnSaveIpUrl) btnSaveIpUrl.addEventListener('click', saveIPUrl);
  if (btnCancelIpUrl) btnCancelIpUrl.addEventListener('click', cancelIPUrlEdit);

  // Bind web search
  if (btnSearchModel) btnSearchModel.addEventListener('click', searchModelOnWeb);
}

async function loadLinksSection(deviceId) {
  const listContainer = document.getElementById(`links-list-${deviceId}`);
  if (!listContainer) return;

  listContainer.innerHTML = '<div class="loading">Chargement des liens...</div>';

  try {
    const links = await apiClient.getDeviceLinks(deviceId);
    listContainer.innerHTML = renderLinksList(links, deviceId);
  } catch (error) {
    console.error('Failed to load links:', error);
    listContainer.innerHTML = `<p style="color: var(--color-danger);">Erreur: ${utils.escapeHtml(error.message || 'Impossible de charger les liens')}</p>`;
  }
}

async function loadBenchmarkHistorySection(deviceId) {
  const container = document.getElementById(`benchmark-history-${deviceId}`);
  if (!container) return;

  try {
    const data = await apiClient.getDeviceBenchmarks(deviceId, { limit: 20 });
    if (!data.items || data.items.length === 0) {
      container.innerHTML = '<p style="color: var(--text-secondary);">Aucun benchmark dans l\'historique.</p>';
      return;
    }

    container.innerHTML = `
      <div class="table-wrapper">
        <table>
          <thead>
            <tr>
              <th>Date</th>
              <th>Global</th>
              <th>CPU</th>
              <th>CPU Mono</th>
              <th>CPU Multi</th>
              <th>Mémoire</th>
              <th>Disque</th>
              <th>Réseau</th>
              <th>GPU</th>
              <th>Version</th>
            </tr>
          </thead>
          <tbody>
            ${data.items.map(bench => `
              <tr>
                <td>${utils.escapeHtml(utils.formatDate(bench.run_at))}</td>
                <td>${formatScoreValue(bench.global_score)}</td>
                <td>${formatScoreValue(bench.cpu_score)}</td>
                <td>${formatScoreValue(bench.cpu_score_single)}</td>
                <td>${formatScoreValue(bench.cpu_score_multi)}</td>
                <td>${formatScoreValue(bench.memory_score)}</td>
                <td>${formatScoreValue(bench.disk_score)}</td>
                <td>${formatScoreValue(bench.network_score)}</td>
                <td>${formatScoreValue(bench.gpu_score)}</td>
                <td>${utils.escapeHtml(bench.bench_script_version || 'N/A')}</td>
              </tr>
            `).join('')}
          </tbody>
        </table>
      </div>
    `;
  } catch (error) {
    console.error('Failed to load benchmark history:', error);
    container.innerHTML = `<p style="color: var(--color-danger);">Erreur: ${utils.escapeHtml(error.message || 'Impossible de charger l\'historique')}</p>`;
  }
}

// Create score card for display
function createScoreCard(score, label, icon) {
  const scoreValue = formatScoreValue(score);
  const badgeClass = score !== null && score !== undefined
    ? utils.getScoreBadgeClass(score)
    : 'badge';

  return `
    <div style="background: var(--bg-secondary); padding: 1rem; border-radius: 6px; text-align: center;">
      <div style="font-size: 1.5rem; margin-bottom: 0.25rem;">${icon}</div>
      <div style="font-size: 0.9rem; color: var(--text-secondary); margin-bottom: 0.5rem;">${label}</div>
      <div class="${badgeClass}" style="font-size: 1.25rem; padding: 0.25rem 0.75rem; display: inline-block;">
        ${scoreValue}
      </div>
    </div>
  `;
}

// Create info card
function createInfoCard(label, value) {
  return `
    <div style="background: var(--bg-secondary); padding: 1rem; border-radius: 6px;">
      <div style="font-weight: 600; margin-bottom: 0.5rem; color: var(--text-primary);">${label}</div>
      <div style="color: var(--text-secondary);">${value}</div>
    </div>
  `;
}

// Create form row (label: value)
function createFormRow(label, value, inline = false) {
  if (inline) {
    return `
      <div style="text-align: center;">
        <div style="font-size: 0.85rem; color: var(--text-secondary); margin-bottom: 0.25rem;">${label}</div>
        <div style="font-weight: 600; color: var(--text-primary); font-size: 1.1rem;">${value}</div>
      </div>
    `;
  }

  return `
    <div style="display: grid; grid-template-columns: 140px 1fr; gap: 1rem; padding: 0.5rem 0; border-bottom: 1px solid var(--border-color);">
      <div style="font-weight: 500; color: var(--text-secondary); font-size: 0.9rem;">${label}</div>
      <div style="color: var(--text-primary); font-size: 0.9rem;">${value}</div>
    </div>
  `;
}

function createSection(id, icon, title, content, options = {}) {
  const iconHtml = icon ? `<span class="section-icon-wrap">${icon}</span>` : '';
  const actionsHtml = options.actionsHtml
    ? `<div class="section-actions">${options.actionsHtml}</div>`
    : '';

  return `
    <section class="device-section" id="${id}">
      <div class="section-header">
        <h3>${iconHtml}<span class="section-title">${title}</span></h3>
        ${actionsHtml}
      </div>
      <div class="section-body">
        ${content}
      </div>
    </section>
  `;
}

function formatRawValue(value) {
  if (value === null || value === undefined || value === '') return 'N/A';
  if (typeof value === 'number') return value;
  return utils.escapeHtml(String(value));
}

function formatScoreValue(value) {
  if (value === null || value === undefined || value === '') return 'N/A';
  const numeric = Number(value);
  if (!Number.isFinite(numeric)) {
    return utils.escapeHtml(String(value));
  }
  return Math.ceil(numeric);
}

function renderUsageBadge(used, total) {
  if (typeof used !== 'number' || typeof total !== 'number' || total <= 0) {
    return '<span class="usage-pill muted">N/A</span>';
  }
  const percent = Math.min(100, Math.max(0, Math.round((used / total) * 100)));
  const modifier = percent >= 85 ? 'high' : percent >= 60 ? 'medium' : 'ok';
  return `<span class="usage-pill ${modifier}">${percent}%</span>`;
}

function formatPriceValue(value) {
  if (value === null || value === undefined || value === '') return 'N/A';
  const numeric = Number(value);
  if (Number.isNaN(numeric)) return utils.escapeHtml(String(value));
  return `${numeric.toFixed(2)} €`;
}

function renderMetadataInput(label, id, value, placeholder = '') {
  return `
    <div style="display: flex; align-items: center; gap: 1rem; margin-bottom: 0.75rem;">
      <div style="width: 140px; font-weight: 500; color: var(--text-secondary); font-size: 0.85rem;">${label}</div>
      <input
        type="text"
        id="${id}"
        value="${utils.escapeHtml(value || '')}"
        placeholder="${utils.escapeHtml(placeholder)}"
        style="flex: 1; padding: 0.4rem 0.6rem; border: 1px solid var(--border-color); border-radius: 4px; background: var(--bg-primary); color: var(--text-primary); font-size: 0.9rem;"
      >
    </div>
  `;
}

function renderMetadataSection(device, bench) {
  const rows = [];
  if (isEditing) {
    return `
      ${renderMetadataInput('Location', 'edit-location', device.location, 'Ex: Datacenter Paris')}
      ${renderMetadataInput('Propriétaire', 'edit-owner', device.owner, 'Responsable')}
      ${renderMetadataInput('Asset Tag', 'edit-asset-tag', device.asset_tag, 'INV-00123')}
      ${createFormRow('Créé le', utils.escapeHtml(new Date(device.created_at).toLocaleString('fr-FR')))}
      ${createFormRow('Mis à jour', utils.escapeHtml(new Date(device.updated_at).toLocaleString('fr-FR')))}
      ${createFormRow('Version bench', utils.escapeHtml(bench?.bench_script_version || 'N/A'))}
    `;
  }

  if (device.location) rows.push(createFormRow('Location', utils.escapeHtml(device.location)));
  if (device.owner) rows.push(createFormRow('Propriétaire', utils.escapeHtml(device.owner)));
  if (device.asset_tag) rows.push(createFormRow('Asset Tag', utils.escapeHtml(device.asset_tag)));
  rows.push(createFormRow('Créé le', utils.escapeHtml(new Date(device.created_at).toLocaleString('fr-FR'))));
  rows.push(createFormRow('Mis à jour', utils.escapeHtml(new Date(device.updated_at).toLocaleString('fr-FR'))));
  rows.push(createFormRow('Version bench', utils.escapeHtml(bench?.bench_script_version || 'N/A')));

  return rows.join('');
}

function renderNetworkBlock(snapshot, bench) {
  if (!snapshot || !snapshot.network_interfaces_json) {
    return '<p style="color: var(--text-secondary);">Aucune information réseau disponible</p>';
  }

  let html = '';

  try {
    const interfaces = typeof snapshot.network_interfaces_json === 'string'
      ? JSON.parse(snapshot.network_interfaces_json)
      : snapshot.network_interfaces_json;

    if (!interfaces || interfaces.length === 0) {
      return '<p style="color: var(--text-secondary);">Aucune interface réseau détectée</p>';
    }

    const hostLabel = snapshot.hostname || currentDevice?.hostname || null;

    html += '<div style="display: grid; gap: 1rem;">';
    interfaces.forEach(iface => {
      const typeIcon = iface.type === 'ethernet' ? '🔌' : (iface.type === 'wifi' ? '📡' : '🌐');
      const wol = iface.wake_on_lan;
      const wolBadge = wol === true
        ? '<span class="badge badge-success" style="margin-left: 0.5rem;">WoL ✓</span>'
        : (wol === false ? '<span class="badge badge-muted" style="margin-left: 0.5rem;">WoL ✗</span>' : '');
      const networkName = iface.network_name || iface.connection_name || iface.profile || iface.ssid || null;

      html += `
        <div style="border: 1px solid var(--border-color); border-radius: 8px; padding: 1rem;">
          <div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 0.75rem;">
            <div>
              <div style="font-weight: 600; color: var(--color-primary); font-size: 1.05rem;">${typeIcon} ${utils.escapeHtml(iface.name || 'N/A')}</div>
              <div style="color: var(--text-secondary); font-size: 0.9rem; margin-top: 0.25rem;">${utils.escapeHtml(iface.type || 'unknown')}</div>
            </div>
            <div>${wolBadge}</div>
          </div>
          <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 0.75rem; font-size: 0.9rem;">
            ${hostLabel ? `<div><strong style="color: var(--text-secondary);">Hostname:</strong><br>${utils.escapeHtml(hostLabel)}</div>` : ''}
            ${networkName ? `<div><strong style="color: var(--text-secondary);">Nom du réseau:</strong><br>${utils.escapeHtml(networkName)}</div>` : ''}
            ${iface.ip ? `<div><strong style="color: var(--text-secondary);">Adresse IP:</strong><br><code>${utils.escapeHtml(iface.ip)}</code></div>` : ''}
            ${iface.mac ? `<div><strong style="color: var(--text-secondary);">MAC:</strong><br><code>${utils.escapeHtml(iface.mac)}</code></div>` : ''}
            ${iface.speed_mbps ? `<div><strong style="color: var(--text-secondary);">Vitesse:</strong><br>${iface.speed_mbps} Mbps</div>` : ''}
            ${iface.driver ? `<div><strong style="color: var(--text-secondary);">Driver:</strong><br>${utils.escapeHtml(iface.driver)}</div>` : ''}
            ${iface.ssid ? `<div><strong style="color: var(--text-secondary);">SSID:</strong><br>${utils.escapeHtml(iface.ssid)}</div>` : ''}
          </div>
        </div>
      `;
    });
    html += '</div>';
  } catch (error) {
    console.error('Failed to parse network interfaces:', error);
    html = '<p style="color: var(--color-danger);">Erreur lors du parsing des données réseau</p>';
  }

  if (bench?.network_results_json) {
    try {
      const netResults = typeof bench.network_results_json === 'string'
        ? JSON.parse(bench.network_results_json)
        : bench.network_results_json;

      html += `
        <div style="margin-top: 1rem; padding: 1rem; background: var(--bg-primary); border-radius: 6px; border: 1px solid var(--border-color);">
          <div style="font-weight: 600; margin-bottom: 0.75rem; color: var(--text-secondary);">📈 Résultats iperf3</div>
          <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 1rem; text-align: center;">
            <div>
              <div style="color: var(--color-success); font-size: 1.5rem; font-weight: 600;">${formatRawValue(netResults.upload_mbps)}</div>
              <div style="font-size: 0.8rem; color: var(--text-secondary);">Upload Mbps</div>
            </div>
            <div>
              <div style="color: var(--color-info); font-size: 1.5rem; font-weight: 600;">${formatRawValue(netResults.download_mbps)}</div>
              <div style="font-size: 0.8rem; color: var(--text-secondary);">Download Mbps</div>
            </div>
            <div>
              <div style="color: var(--color-warning); font-size: 1.5rem; font-weight: 600;">${formatRawValue(netResults.ping_ms)}</div>
              <div style="font-size: 0.8rem; color: var(--text-secondary);">Ping ms</div>
            </div>
            <div>
              <div style="color: var(--color-purple); font-size: 1.5rem; font-weight: 600;">${formatScoreValue(netResults.score)}</div>
              <div style="font-size: 0.8rem; color: var(--text-secondary);">Score</div>
            </div>
          </div>
        </div>
      `;
    } catch (error) {
      console.error('Failed to parse network benchmark results:', error);
    }
  }

  return html;
}

function renderNetworkSharesDetails(snapshot) {
  if (!snapshot || !snapshot.network_shares_json) {
    return '<p style="color: var(--text-secondary);">Aucun partage réseau détecté</p>';
  }

  try {
    const shares = typeof snapshot.network_shares_json === 'string'
      ? JSON.parse(snapshot.network_shares_json)
      : snapshot.network_shares_json;

    if (!Array.isArray(shares) || shares.length === 0) {
      return '<p style="color: var(--text-secondary);">Aucun partage réseau monté</p>';
    }

    return `
      <div class="table-wrapper">
        <table>
          <thead>
            <tr>
              <th>Source</th>
              <th>Montage</th>
              <th>Protocole</th>
              <th>Type</th>
              <th>Utilisé</th>
              <th>Libre</th>
              <th>Total</th>
              <th>Options</th>
            </tr>
          </thead>
          <tbody>
            ${shares.map(share => `
              <tr>
                <td>${utils.escapeHtml(share.source || 'N/A')}</td>
                <td>${utils.escapeHtml(share.mount_point || 'N/A')}</td>
                <td>${utils.escapeHtml(share.protocol || share.fs_type || 'N/A')}</td>
                <td>${share.fs_type ? utils.escapeHtml(share.fs_type) : 'N/A'}</td>
                <td>${typeof share.used_gb === 'number' ? utils.formatStorage(share.used_gb, 'GB') : 'N/A'}</td>
                <td>${typeof share.free_gb === 'number' ? utils.formatStorage(share.free_gb, 'GB') : 'N/A'}</td>
                <td>${typeof share.total_gb === 'number' ? utils.formatStorage(share.total_gb, 'GB') : 'N/A'}</td>
                <td>${share.options ? utils.escapeHtml(share.options) : 'N/A'}</td>
              </tr>
            `).join('')}
          </tbody>
        </table>
      </div>
    `;
  } catch (error) {
    console.error('Failed to parse network shares:', error);
    return '<p style="color: var(--color-danger);">Erreur lors de la lecture des partages réseau</p>';
  }
}

function renderBenchmarkSection(deviceId, bench) {
  if (!bench) {
    return '<p style="color: var(--text-secondary);">Aucun benchmark disponible pour ce device.</p>';
  }

  const rows = [
    { label: 'Score global', value: formatScoreValue(bench.global_score) },
    { label: 'CPU score', value: formatScoreValue(bench.cpu_score) },
    { label: 'CPU single', value: formatScoreValue(bench.cpu_score_single) },
    { label: 'CPU multi', value: formatScoreValue(bench.cpu_score_multi) },
    { label: 'Mémoire', value: formatScoreValue(bench.memory_score) },
    { label: 'Disque', value: formatScoreValue(bench.disk_score) },
    { label: 'Réseau', value: formatScoreValue(bench.network_score) },
    { label: 'GPU', value: formatScoreValue(bench.gpu_score) },
    { label: 'Exécuté le', value: utils.escapeHtml(utils.formatDate(bench.run_at)) }
  ];

  return `
    <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 0.75rem;">
      ${rows.map(row => `
        <div style="padding: 0.75rem; background: var(--bg-primary); border-radius: 6px; border: 1px solid var(--border-color);">
          <div style="font-size: 0.8rem; color: var(--text-secondary); margin-bottom: 0.25rem;">${row.label}</div>
          <div style="font-weight: 600; font-size: 1rem;">${row.value}</div>
        </div>
      `).join('')}
    </div>
    <div style="margin-top: 1rem; display: flex; gap: 0.75rem; flex-wrap: wrap;">
      <button class="btn btn-secondary btn-sm" onclick="viewBenchmarkDetails(${bench.id})">📋 Voir les détails JSON</button>
    </div>
    <div id="benchmark-history-${deviceId}" style="margin-top: 1.5rem;">
      <div class="loading">Chargement de l'historique...</div>
    </div>
  `;
}

function renderTagsSection(device) {
  const tags = utils.parseTags(device.tags);
  const chips = tags.length
    ? `
      <div class="tags">
        ${tags.map(tag => `
          <span class="tag tag-primary">
            ${utils.escapeHtml(tag)}
            <button type="button" class="remove-tag" title="Supprimer ${utils.escapeHtml(tag)}" onclick="removeTag(${utils.escapeHtml(JSON.stringify(tag))})">×</button>
          </span>
        `).join('')}
      </div>
    `
    : '<p style="color: var(--text-secondary);">Aucun tag configuré</p>';

  return `
    ${chips}
    <div class="tag-form">
      <input
        type="text"
        id="new-tag-input-${device.id}"
        placeholder="Ajouter un tag"
      >
      <button class="icon-btn" title="Ajouter un tag" onclick="addTag()" type="button">
        <img src="icons/icons8-done-48.png" alt="Ajouter un tag">
      </button>
    </div>
  `;
}

function renderNotesSection(device) {
  if (editingNotes) {
    return `
      <textarea
        id="notes-editor"
        rows="6"
        style="width: 100%; padding: 0.75rem; border: 1px solid var(--border-color); border-radius: 6px; background: var(--bg-primary); color: var(--text-primary); font-family: inherit; resize: vertical;"
        placeholder="Notes techniques, incidents, TODO..."
      >${utils.escapeHtml(device.description || '')}</textarea>
    `;
  }

  return utils.renderMarkdown(device.description || 'Aucune note enregistrée.');
}

function renderPurchaseSection(device) {
  const infoRows = [
    { label: 'Boutique', value: device.purchase_store || 'Non renseigné' },
    { label: 'Date d\'achat', value: device.purchase_date || 'Non renseigné' },
    { label: 'Prix', value: formatPriceValue(device.purchase_price) }
  ];

  let infoHtml = '';
  if (editingPurchase) {
    infoHtml = `
      <div class="inline-form">
        <input id="purchase-store-input" type="text" placeholder="Boutique / Revendeur" value="${utils.escapeHtml(device.purchase_store || '')}">
        <input id="purchase-date-input" type="date" value="${device.purchase_date || ''}">
        <input id="purchase-price-input" type="number" step="0.01" placeholder="Prix en €" value="${device.purchase_price != null ? device.purchase_price : ''}">
      </div>
    `;
  } else {
    infoHtml = `
      <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 0.75rem;">
        ${infoRows.map(row => `
          <div style="padding: 0.75rem; background: var(--bg-primary); border-radius: 6px; border: 1px solid var(--border-color);">
            <div style="font-size: 0.8rem; color: var(--text-secondary); margin-bottom: 0.25rem;">${row.label}</div>
            <div style="font-weight: 600;">${utils.escapeHtml(String(row.value))}</div>
          </div>
        `).join('')}
      </div>
    `;
  }

  const docs = device.documents || [];
  const invoices = docs.filter(doc => ['invoice', 'warranty'].includes(doc.doc_type));
  const docsHtml = invoices.length
    ? `
      <ul style="list-style: none; padding-left: 0; display: grid; gap: 0.5rem; margin-top: 1rem;">
        ${invoices.map(doc => `
          <li style="border: 1px solid var(--border-color); border-radius: 6px; padding: 0.75rem; background: var(--bg-primary);">
            <div style="font-weight: 600; color: var(--text-primary);">${doc.doc_type === 'invoice' ? 'Facture' : 'Garantie'} • ${utils.escapeHtml(doc.filename)}</div>
            <div style="font-size: 0.85rem; color: var(--text-secondary);">Uploadé le ${utils.formatDate(doc.uploaded_at)} • ${utils.formatFileSize(doc.size_bytes)}</div>
          </li>
        `).join('')}
      </ul>
    `
    : '<p style="color: var(--text-secondary); margin-top: 1rem;">Aucune facture ou garantie uploadée.</p>';

  return infoHtml + docsHtml;
}

function renderUpgradeSection(bench) {
  if (!bench) {
    return '<p style="color: var(--text-secondary);">Aucun benchmark disponible.</p>';
  }

  if (editingUpgradeNotes) {
    return `
      <textarea
        id="upgrade-notes-editor"
        rows="6"
        style="width: 100%; padding: 0.75rem; border: 1px solid var(--border-color); border-radius: 6px; background: var(--bg-primary); color: var(--text-primary); font-family: inherit; resize: vertical;"
        placeholder="Consignez les upgrades à prévoir, pièces remplacées, etc."
      >${utils.escapeHtml(bench.notes || '')}</textarea>
    `;
  }

  if (bench.notes) {
    return utils.renderMarkdown(bench.notes);
  }

  return '<p style="color: var(--text-secondary);">Aucune note d\'upgrade enregistrée sur le dernier benchmark.</p>';
}

function renderLinksPlaceholder(deviceId) {
  return `
    <div class="links-form">
      <input
        type="text"
        id="link-label-${deviceId}"
        placeholder="Libellé (ex: Support, Datasheet)"
        style="flex: 1;"
      >
      <input
        type="url"
        id="link-url-${deviceId}"
        placeholder="https://..."
        style="flex: 1;"
      >
      <button class="icon-btn" title="Ajouter un lien" onclick="addDeviceLinkEntry(${deviceId})" type="button">
        <img src="icons/icons8-done-48.png" alt="Ajouter">
      </button>
    </div>
    <div id="links-list-${deviceId}" class="loading">Chargement des liens...</div>
  `;
}

function renderLinksList(links, deviceId) {
  if (!links || links.length === 0) {
    return '<p style="color: var(--text-secondary);">Aucun lien enregistré.</p>';
  }

  return `
    <ul style="list-style: none; padding-left: 0; display: grid; gap: 0.5rem;">
      ${links.map(link => `
        <li style="border: 1px solid var(--border-color); border-radius: 6px; padding: 0.75rem; background: var(--bg-primary); display: flex; justify-content: space-between; align-items: center; gap: 0.5rem;">
          <div>
            <div style="font-weight: 600;">${utils.escapeHtml(link.label)}</div>
            <div style="font-size: 0.85rem;"><a href="${utils.escapeHtml(link.url)}" target="_blank" rel="noopener">${utils.escapeHtml(link.url)}</a></div>
          </div>
          <button class="icon-btn danger" title="Supprimer le lien" onclick="deleteDeviceLink(${link.id}, ${deviceId})" type="button">
            <img src="icons/icons8-delete-48.png" alt="Supprimer">
          </button>
        </li>
      `).join('')}
    </ul>
  `;
}

function renderEmptyDetailsPlaceholder() {
  return `
    <div style="text-align: center; color: var(--text-secondary); padding: 4rem 2rem;">
      <div style="font-size: 3rem; margin-bottom: 1rem;">📊</div>
      <p style="font-size: 1.1rem;">Sélectionnez un device dans la liste pour afficher ses détails</p>
    </div>
  `;
}

// Initialize devices page
document.addEventListener('DOMContentLoaded', () => {
  loadDevices();

  // Refresh every 30 seconds
  setInterval(loadDevices, 30000);
});

// Preview image in modal
function previewImage(docId, filename) {
  const downloadUrl = apiClient.getDocumentDownloadUrl(docId);

  const modalHtml = `
    <div id="imagePreviewModal" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.9); z-index: 10000; display: flex; align-items: center; justify-content: center; flex-direction: column;" onclick="closeImagePreview()">
      <div style="position: absolute; top: 20px; right: 20px; color: white; font-size: 2rem; cursor: pointer; z-index: 10001;" onclick="closeImagePreview()">×</div>
      <img src="${downloadUrl}" alt="${utils.escapeHtml(filename)}" style="max-width: 90%; max-height: 90vh; object-fit: contain;" onclick="event.stopPropagation()">
      <div style="color: white; margin-top: 1rem; font-size: 1.1rem;">${utils.escapeHtml(filename)}</div>
    </div>
  `;

  document.body.insertAdjacentHTML('beforeend', modalHtml);
}

function closeImagePreview() {
  const modal = document.getElementById('imagePreviewModal');
  if (modal) {
    modal.remove();
  }
}

// Preview PDF in modal
function previewPDF(docId, filename) {
  const downloadUrl = apiClient.getDocumentDownloadUrl(docId);

  const modalHtml = `
    <div id="pdfPreviewModal" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.9); z-index: 10000; display: flex; align-items: center; justify-content: center; flex-direction: column;">
      <div style="width: 90%; height: 90vh; background: white; border-radius: 8px; display: flex; flex-direction: column;">
        <div style="display: flex; justify-content: space-between; align-items: center; padding: 1rem; background: var(--bg-secondary); border-bottom: 2px solid var(--border-color); border-radius: 8px 8px 0 0;">
          <h3 style="margin: 0; color: var(--text-primary);">📄 ${utils.escapeHtml(filename)}</h3>
          <button onclick="closePDFPreview()" style="background: var(--color-danger); color: white; border: none; padding: 0.5rem 1rem; border-radius: 4px; cursor: pointer; font-size: 1rem;">✖ Fermer</button>
        </div>
        <iframe src="${downloadUrl}" style="flex: 1; border: none; width: 100%;"></iframe>
      </div>
    </div>
  `;

  document.body.insertAdjacentHTML('beforeend', modalHtml);
}

function closePDFPreview() {
  const modal = document.getElementById('pdfPreviewModal');
  if (modal) {
    modal.remove();
  }
}

// Make functions available globally for onclick handlers
window.selectDevice = selectDevice;
window.deleteDocument = deleteDocument;
window.viewBenchmarkDetails = viewBenchmarkDetails;
window.previewImage = previewImage;
window.closeImagePreview = closeImagePreview;
window.previewPDF = previewPDF;
window.closePDFPreview = closePDFPreview;
window.deleteDeviceFromList = deleteDeviceFromList;
window.startNotesEdit = startNotesEdit;
window.cancelNotesEdit = cancelNotesEdit;
window.saveNotes = saveNotes;
window.clearNotes = clearNotes;
window.startUpgradeNotesEdit = startUpgradeNotesEdit;
window.cancelUpgradeNotesEdit = cancelUpgradeNotesEdit;
window.saveUpgradeNotes = saveUpgradeNotes;
window.clearUpgradeNotes = clearUpgradeNotes;
window.startPurchaseEdit = startPurchaseEdit;
window.cancelPurchaseEdit = cancelPurchaseEdit;
window.savePurchaseInfo = savePurchaseInfo;
window.addTag = addTag;
window.removeTag = removeTag;
window.addDeviceLinkEntry = addDeviceLinkEntry;
window.deleteDeviceLink = deleteDeviceLink;

})(); // End of IIFE
