// Configuration et état
let config = null;
let charts = new Map(); // Map des graphiques Chart.js
let updateInterval = null;
let currentTabIndex = 0;
let totalTabs = 0;
let consecutiveErrors = 0;
const MAX_CONSECUTIVE_ERRORS = 3;

// Variables pour les apps
let appsRendered = false;
let lastAppsTabId = null;

// Variables pour le swipe
let touchStartX = 0;
let touchEndX = 0;
let touchStartY = 0;
let touchEndY = 0;
const SWIPE_THRESHOLD = 50; // Minimum de pixels pour déclencher un swipe

// Initialisation
document.addEventListener('DOMContentLoaded', async () => {
    await loadConfig();
    await loadData();
    
    // Initialiser le swipe
    initSwipeGestures();
    
    // Démarrer les mises à jour automatiques (toutes les 2 secondes)
    updateInterval = setInterval(loadData, 2000);
});

// === Chargement configuration ===
async function loadConfig() {
    try {
        const response = await fetch('/api/config');
        config = await response.json();
        
        // Appliquer le thème
        document.documentElement.setAttribute('data-theme', config.theme || 'dark');
        
        // Réinitialiser le flag de rendu des apps (la config peut avoir changé)
        appsRendered = false;
        
        // Les apps seront rendues dans loadData() après création des panes
        
    } catch (error) {
        console.error('Erreur chargement config:', error);
        showError('Impossible de charger la configuration');
    }
}

// === Chargement données ===
async function loadData() {
    try {
        const response = await fetch('/api/lhm/data');
        const data = await response.json();
        
        if (data.error) {
            consecutiveErrors++;
            if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
                showError(data.error);
            }
            return;
        }
        
        // Réinitialiser le compteur d'erreurs en cas de succès
        consecutiveErrors = 0;
        
        // Cacher les états d'erreur/vide
        document.getElementById('error-state').style.display = 'none';
        
        // Vérifier s'il y a des capteurs OU des apps configurés
        const hasSensors = data.tabs.some(tab => tab.sensors.length > 0);
        const hasApps = config && config.apps && config.apps.length > 0;
        
        if (!hasSensors && !hasApps) {
            document.getElementById('empty-state').style.display = 'block';
            document.getElementById('tabs-nav').style.display = 'none';
            document.getElementById('tabs-content').style.display = 'none';
            return;
        }
        
        document.getElementById('empty-state').style.display = 'none';
        
        // Render les onglets et données
        renderTabs(data.tabs);
        renderSensors(data.tabs);
        
        // Render les apps (dans le bon onglet ou section séparée)
        try {
            renderApps();
        } catch (appError) {
            console.error('Erreur rendu apps:', appError);
        }
        
        // Mettre à jour le timestamp
        updateTimestamp();
        
    } catch (error) {
        console.error('Erreur chargement données:', error);
        consecutiveErrors++;
        
        // N'afficher l'erreur que si plusieurs échecs consécutifs
        // et qu'il n'y a pas déjà du contenu affiché
        if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
            const tabsContent = document.getElementById('tabs-content');
            if (!tabsContent || tabsContent.children.length === 0) {
                showError('Erreur de connexion à LibreHardwareMonitor');
            }
        }
    }
}

// === Render onglets ===
function renderTabs(tabs) {
    const tabsNav = document.getElementById('tabs-nav');
    
    // Mettre à jour le nombre total d'onglets
    totalTabs = tabs.length;
    
    // Si un seul onglet, on ne l'affiche pas mais on crée quand même le swipe indicator
    if (tabs.length === 1) {
        tabsNav.style.display = 'none';
        removeSwipeIndicators();
        return;
    }
    
    tabsNav.style.display = 'flex';
    
    // Ne re-render que si nécessaire
    if (tabsNav.dataset.rendered !== 'true') {
        tabsNav.innerHTML = '';
        
        tabs.forEach((tab, index) => {
            const button = document.createElement('button');
            button.className = 'tab-button' + (index === 0 ? ' active' : '');
            button.textContent = tab.name;
            button.dataset.tabId = tab.id;
            button.dataset.tabIndex = index;
            button.addEventListener('click', () => switchTab(tab.id));
            tabsNav.appendChild(button);
        });
        
        tabsNav.dataset.rendered = 'true';
        
        // Créer les indicateurs de swipe
        createSwipeIndicators(tabs.length);
    }
}

function createSwipeIndicators(count) {
    // Supprimer les anciens indicateurs
    removeSwipeIndicators();
    
    if (count <= 1) return;
    
    const container = document.createElement('div');
    container.className = 'swipe-indicators';
    container.id = 'swipe-indicators';
    
    for (let i = 0; i < count; i++) {
        const dot = document.createElement('span');
        dot.className = 'swipe-dot' + (i === 0 ? ' active' : '');
        dot.dataset.index = i;
        dot.addEventListener('click', () => switchTabByIndex(i));
        container.appendChild(dot);
    }
    
    // Ajouter après les tabs-nav
    const tabsNav = document.getElementById('tabs-nav');
    tabsNav.parentNode.insertBefore(container, tabsNav.nextSibling);
}

function removeSwipeIndicators() {
    const existing = document.getElementById('swipe-indicators');
    if (existing) {
        existing.remove();
    }
}

function switchTab(tabId) {
    // Désactiver tous les tabs
    document.querySelectorAll('.tab-button').forEach(btn => {
        btn.classList.remove('active');
    });
    
    // Activer le bon
    const activeBtn = document.querySelector(`.tab-button[data-tab-id="${tabId}"]`);
    if (activeBtn) {
        activeBtn.classList.add('active');
        // Mettre à jour l'index courant
        currentTabIndex = parseInt(activeBtn.dataset.tabIndex) || 0;
    }
    
    // Basculer les panes
    document.querySelectorAll('.tab-pane').forEach(pane => {
        pane.classList.remove('active');
    });
    
    const targetPane = document.getElementById(`pane-${tabId}`);
    if (targetPane) {
        targetPane.classList.add('active');
    }
    
    // Mettre à jour les indicateurs
    updateSwipeIndicators();
}

function switchTabByIndex(index) {
    const buttons = document.querySelectorAll('.tab-button');
    if (index >= 0 && index < buttons.length) {
        const tabId = buttons[index].dataset.tabId;
        switchTab(tabId);
    }
}

function updateSwipeIndicators() {
    const indicators = document.querySelectorAll('.swipe-dot');
    indicators.forEach((dot, index) => {
        dot.classList.toggle('active', index === currentTabIndex);
    });
}

// === Render capteurs ===
function renderSensors(tabs) {
    const tabsContent = document.getElementById('tabs-content');
    tabsContent.style.display = 'block';
    
    // Créer les panes si nécessaire
    tabs.forEach((tab, index) => {
        let pane = document.getElementById(`pane-${tab.id}`);
        
        if (!pane) {
            pane = document.createElement('div');
            pane.id = `pane-${tab.id}`;
            pane.className = 'tab-pane' + (index === 0 ? ' active' : '');
            tabsContent.appendChild(pane);
        }
        
        // Créer le grid de capteurs
        let grid = pane.querySelector('.sensors-grid');
        if (!grid) {
            grid = document.createElement('div');
            grid.className = 'sensors-grid';
            pane.appendChild(grid);
        }
        
        // Render chaque capteur
        tab.sensors.forEach(sensor => {
            console.log('--- Render sensor:', sensor.name, 'show_graph:', sensor.show_graph, 'viz_type:', sensor.viz_type);
            
            let card = grid.querySelector(`[data-sensor-id="${CSS.escape(sensor.id)}"]`);
            
            // Déterminer le viz_type à utiliser
            const vizType = sensor.show_graph ? (sensor.viz_type || 'line') : 'none';
            
            // Vérifier si on doit recréer la carte
            let needsRecreation = false;
            if (card) {
                const currentVizType = card.dataset.vizType || 'none';
                const currentShowTypeBadge = card.dataset.showTypeBadge !== 'false';
                const newShowTypeBadge = sensor.show_type_badge !== false;
                const currentFontFamily = card.dataset.fontFamily || 'system';
                const newFontFamily = sensor.font_family || 'system';
                const currentFontBold = card.dataset.fontBold !== 'false';
                const newFontBold = sensor.font_bold !== false;
                
                // Recréer si le type de visualisation a changé
                if (currentVizType !== vizType) {
                    console.log(`⚠️ Changement de visualisation: ${currentVizType} → ${vizType}, recréation carte`);
                    needsRecreation = true;
                    
                    // Supprimer l'ancien graphique du Map si existant
                    if (charts.has(sensor.id)) {
                        const oldChart = charts.get(sensor.id);
                        // Détruire proprement si c'est un Chart.js
                        if (oldChart && typeof oldChart.destroy === 'function') {
                            oldChart.destroy();
                        }
                        charts.delete(sensor.id);
                    }
                }
                // Recréer si l'option badge a changé
                else if (currentShowTypeBadge !== newShowTypeBadge) {
                    console.log(`⚠️ Changement badge type: ${currentShowTypeBadge} → ${newShowTypeBadge}, recréation carte`);
                    needsRecreation = true;
                }
                // Recréer si la police a changé
                else if (currentFontFamily !== newFontFamily) {
                    console.log(`⚠️ Changement police: ${currentFontFamily} → ${newFontFamily}, recréation carte`);
                    needsRecreation = true;
                }
                // Recréer si le bold a changé
                else if (currentFontBold !== newFontBold) {
                    console.log(`⚠️ Changement bold: ${currentFontBold} → ${newFontBold}, recréation carte`);
                    needsRecreation = true;
                }
                // Vérifier aussi si le canvas manque
                else if (sensor.show_graph) {
                    if (vizType === 'gauge' && !card.querySelector('.sensor-gauge')) {
                        console.log('⚠️ Jauge manquante, recréation carte');
                        needsRecreation = true;
                    } else if (vizType === 'line' && !card.querySelector('.sensor-chart')) {
                        console.log('⚠️ Graphique manquant, recréation carte');
                        needsRecreation = true;
                    }
                }
            }
            
            if (!card || needsRecreation) {
                console.log(needsRecreation ? 'Recréation carte...' : 'Carte n\'existe pas, création...');
                
                // Supprimer l'ancienne si elle existe
                if (card) {
                    card.remove();
                }
                
                // Créer un objet sensor modifié pour l'affichage
                const sensorForDisplay = {
                    ...sensor,
                    viz_type: sensor.show_graph ? (sensor.viz_type || 'line') : 'none'
                };
                
                // Créer la carte
                card = createSensorCard(sensorForDisplay);
                grid.appendChild(card);
                
                // Créer la visualisation si nécessaire
                if (sensor.show_graph) {
                    console.log('show_graph = true, création visualisation...');
                    if (vizType === 'gauge') {
                        console.log('→ Appel createGauge');
                        createGauge(sensorForDisplay);
                    } else {
                        console.log('→ Appel createChart');
                        createChart(sensorForDisplay);
                    }
                } else {
                    console.log('show_graph = false, pas de visualisation');
                }
            } else {
                // Mettre à jour la valeur
                updateSensorCard(card, sensor);
            }
            
            // Mettre à jour la visualisation
            if (sensor.show_graph && charts.has(sensor.id)) {
                if (vizType === 'gauge') {
                    updateGauge(sensor);
                } else {
                    updateChart(sensor);
                }
            }
        });
    });
}

function createSensorCard(sensor) {
    console.log('=== createSensorCard ===');
    console.log('Sensor:', sensor);
    console.log('show_graph:', sensor.show_graph);
    console.log('viz_type:', sensor.viz_type);
    
    const card = document.createElement('div');
    card.className = 'sensor-card';
    
    // Ajouter la classe de taille
    const cardSize = sensor.card_size || 'medium';
    card.classList.add(`card-${cardSize}`);
    
    // Ajouter la classe de police
    const fontFamily = sensor.font_family || 'system';
    card.classList.add(`font-family-${fontFamily}`);
    
    // Ajouter la classe bold/normal
    const fontBold = sensor.font_bold !== false; // true par défaut
    card.classList.add(fontBold ? 'font-bold' : 'font-normal');
    
    // Ajouter la classe de taille de police
    const fontSize = sensor.font_size || 'small';
    card.classList.add(`font-${fontSize}`);
    
    // Ajouter la classe pour masquer la valeur sur mobile si activé
    if (sensor.hide_value_mobile) {
        card.classList.add('hide-value-mobile');
    }
    
    card.dataset.sensorId = sensor.id;
    card.dataset.vizType = sensor.show_graph ? (sensor.viz_type || 'line') : 'none';
    card.dataset.showTypeBadge = sensor.show_type_badge !== false ? 'true' : 'false';
    card.dataset.fontFamily = fontFamily;
    card.dataset.fontBold = fontBold ? 'true' : 'false';
    
    const valueClass = getSensorValueClass(sensor);
    
    // Déterminer quel type de visualisation afficher
    let vizHtml = '';
    if (sensor.show_graph && sensor.viz_type === 'gauge') {
        console.log('→ Création HTML jauge DIRECTE');
        const gaugeSize = (sensor.gauge_options && sensor.gauge_options.size) || 'medium';
        // Définir les dimensions selon la taille
        const gaugeSizes = {
            tiny: 60,
            xs: 90,
            small: 120,
            medium: 180,
            large: 240
        };
        const size = gaugeSizes[gaugeSize] || 180;
        // Canvas DIRECT avec dimensions explicites
        vizHtml = `<canvas class="sensor-gauge gauge-${gaugeSize}" width="${size}" height="${size}"></canvas>`;
    } else if (sensor.show_graph && (sensor.viz_type === 'line' || !sensor.viz_type)) {
        console.log('→ Création HTML courbe DIRECTE');
        const chartHeight = (sensor.chart_options && sensor.chart_options.height) || 'medium';
        // Définir les hauteurs selon la taille
        const chartHeights = {
            tiny: 50,
            xs: 70,
            small: 90,
            medium: 120,
            large: 180
        };
        const height = chartHeights[chartHeight] || 120;
        // Canvas DIRECT avec dimensions explicites (width sera 100%)
        vizHtml = `<canvas class="sensor-chart chart-${chartHeight}" height="${height}"></canvas>`;
    } else {
        console.log('→ Pas de visualisation');
    }
    
    // Badge de type (affiché par défaut, peut être masqué)
    const showTypeBadge = sensor.show_type_badge !== false;
    const typeBadgeHtml = showTypeBadge ? `<div class="sensor-type-badge">${sensor.type}</div>` : '';
    
    card.innerHTML = `
        <div class="sensor-header">
            <div class="sensor-name">${sensor.name}</div>
            ${typeBadgeHtml}
        </div>
        <div class="sensor-value ${valueClass}" data-value>${sensor.value}</div>
        ${vizHtml}
    `;
    
    console.log('HTML carte créée avec canvas DIRECT');
    return card;
}

function updateSensorCard(card, sensor) {
    const valueDiv = card.querySelector('[data-value]');
    valueDiv.textContent = sensor.value;
    valueDiv.className = 'sensor-value ' + getSensorValueClass(sensor);
}

function getSensorValueClass(sensor) {
    let classes = [sensor.type];
    
    // Ajouter des classes selon la valeur
    if (sensor.type === 'temperature') {
        const temp = parseFloat(sensor.value);
        if (temp < 40) classes.push('cold');
        else if (temp > 70) classes.push('hot');
    } else if (sensor.type === 'percentage') {
        const percent = parseFloat(sensor.value);
        if (percent > 90) classes.push('critical');
        else if (percent > 70) classes.push('high');
    }
    
    return classes.join(' ');
}

// === Graphiques Chart.js ===
function createChart(sensor) {
    console.log('=== createChart appelé ===');
    console.log('Sensor:', sensor);
    
    const sensorId = sensor.id;
    const card = document.querySelector(`[data-sensor-id="${CSS.escape(sensorId)}"]`);
    
    console.log('Card trouvée:', card);
    if (!card) {
        console.error('ERREUR: Card non trouvée pour', sensorId);
        return;
    }
    
    const canvas = card.querySelector('.sensor-chart');
    console.log('Canvas trouvé:', canvas);
    
    if (!canvas) {
        console.error('ERREUR: Canvas .sensor-chart non trouvé dans la carte');
        return;
    }
    
    const ctx = canvas.getContext('2d');
    console.log('Context 2D:', ctx);
    
    // Obtenir le type de capteur
    const sensorType = sensor.type || 'generic';
    
    // Couleurs selon le type
    let borderColor, backgroundColor;
    switch(sensorType) {
        case 'temperature':
            borderColor = 'rgba(255, 152, 0, 1)';  // Orange
            backgroundColor = 'rgba(255, 152, 0, 0.1)';
            break;
        case 'percentage':
        case 'load':
            borderColor = 'rgba(74, 158, 255, 1)';  // Bleu
            backgroundColor = 'rgba(74, 158, 255, 0.1)';
            break;
        case 'fan':
            borderColor = 'rgba(76, 175, 80, 1)';  // Vert
            backgroundColor = 'rgba(76, 175, 80, 0.1)';
            break;
        case 'power':
            borderColor = 'rgba(244, 67, 54, 1)';  // Rouge
            backgroundColor = 'rgba(244, 67, 54, 0.1)';
            break;
        case 'voltage':
            borderColor = 'rgba(156, 39, 176, 1)';  // Violet
            backgroundColor = 'rgba(156, 39, 176, 0.1)';
            break;
        case 'frequency':
        case 'clock':
            borderColor = 'rgba(255, 193, 7, 1)';  // Jaune
            backgroundColor = 'rgba(255, 193, 7, 0.1)';
            break;
        default:
            borderColor = 'rgba(74, 158, 255, 1)';
            backgroundColor = 'rgba(74, 158, 255, 0.1)';
    }
    
    console.log('Création Chart.js...');
    const chart = new Chart(ctx, {
        type: 'line',
        data: {
            labels: [],
            datasets: [{
                data: [],
                borderColor: borderColor,
                backgroundColor: backgroundColor,
                borderWidth: 2,
                tension: 0.4,
                pointRadius: 0,
                fill: true
            }]
        },
        options: {
            responsive: true,
            maintainAspectRatio: false,
            plugins: {
                legend: { display: false },
                tooltip: { enabled: false }
            },
            scales: {
                x: { display: false },
                y: { 
                    display: true,
                    grid: {
                        color: 'rgba(255, 255, 255, 0.05)',
                        drawBorder: false
                    },
                    ticks: {
                        color: 'rgba(255, 255, 255, 0.3)',
                        font: { size: 10 }
                    }
                }
            },
            animation: { duration: 0 }
        }
    });
    
    console.log('Chart créé:', chart);
    charts.set(sensorId, chart);
    console.log('Chart stocké dans Map');
    
    // Charger l'historique initial
    console.log('Chargement historique initial...');
    updateChart(sensor);
}

async function updateChart(sensor) {
    console.log('=== updateChart appelé ===', sensor.name);
    
    const sensorId = sensor.id;
    const chart = charts.get(sensorId);
    if (!chart) {
        console.error('ERREUR: Chart non trouvé dans Map pour', sensorId);
        return;
    }
    
    // Vérifier si le chart est dans un onglet actif
    const canvas = chart.canvas;
    if (canvas) {
        const pane = canvas.closest('.tab-pane');
        if (pane && !pane.classList.contains('active')) {
            // Le chart est dans un onglet inactif, ne pas mettre à jour
            return;
        }
    }
    
    try {
        console.log('Fetch historique pour', sensorId);
        const response = await fetch(`/api/lhm/history/${encodeURIComponent(sensorId)}?count=60`);
        const data = await response.json();
        
        console.log('Historique reçu:', data);
        
        if (data.values && data.values.length > 0) {
            console.log('→ Mise à jour chart avec', data.values.length, 'valeurs');
            chart.data.labels = data.values.map((_, i) => i);
            chart.data.datasets[0].data = data.values;
            chart.update('none');
            console.log('→ Chart mis à jour');
        } else {
            console.warn('→ Pas de valeurs dans l\'historique');
        }
    } catch (error) {
        console.error('Erreur mise à jour graphique:', sensorId, error);
    }
}

// === Jauges circulaires ===
function createGauge(sensor) {
    console.log('=== createGauge appelé ===');
    console.log('Sensor:', sensor);
    
    const sensorId = sensor.id;
    const card = document.querySelector(`[data-sensor-id="${CSS.escape(sensorId)}"]`);
    
    console.log('Card trouvée:', card);
    if (!card) {
        console.error('ERREUR: Card non trouvée pour', sensorId);
        return;
    }
    
    const canvas = card.querySelector('.sensor-gauge');
    console.log('Canvas trouvé:', canvas);
    
    if (!canvas) {
        console.error('ERREUR: Canvas .sensor-gauge non trouvé dans la carte');
        console.log('HTML de la card:', card.innerHTML);
        return;
    }
    
    // Stocker les infos de la jauge
    charts.set(sensorId, {
        type: 'gauge',
        canvas: canvas,
        sensor: sensor
    });
    
    console.log('Jauge stockée dans Map, dessin initial...');
    
    // Dessiner la jauge initiale
    updateGauge(sensor);
}

function updateGauge(sensor) {
    console.log('=== updateGauge appelé ===', sensor.name);
    
    const sensorId = sensor.id;
    const gaugeInfo = charts.get(sensorId);
    if (!gaugeInfo || gaugeInfo.type !== 'gauge') {
        console.error('ERREUR: gaugeInfo non trouvé ou pas de type gauge');
        return;
    }
    
    const canvas = gaugeInfo.canvas;
    if (!canvas) {
        console.error('ERREUR: canvas non trouvé');
        return;
    }
    
    // Vérifier si le canvas est visible (dans un onglet actif)
    const pane = canvas.closest('.tab-pane');
    if (pane && !pane.classList.contains('active')) {
        // Le canvas est dans un onglet inactif, ne pas dessiner
        return;
    }
    
    const ctx = canvas.getContext('2d');
    
    console.log('Canvas:', canvas, 'offsetWidth:', canvas.offsetWidth);
    
    // Définir la taille - protection contre taille nulle ou trop petite
    const size = canvas.offsetWidth || canvas.width || 60;
    if (size < 20) {
        console.warn('Canvas trop petit, skip updateGauge');
        return;
    }
    
    canvas.width = size;
    canvas.height = size;
    
    console.log('Taille canvas:', size);
    
    // Extraire la valeur numérique
    const valueStr = sensor.value.replace(/[^\d.,]/g, '').replace(',', '.');
    let value = parseFloat(valueStr);
    if (isNaN(value)) value = 0;
    
    console.log('Valeur extraite:', value);
    
    // Déterminer min, max selon le type
    let min = 0, max = 100;
    const sensorType = sensor.type || 'generic';
    
    switch(sensorType) {
        case 'temperature':
            min = 0;
            max = 100; // 0-100°C
            break;
        case 'percentage':
        case 'load':
            min = 0;
            max = 100;
            break;
        case 'fan':
            min = 0;
            max = 2000; // 0-2000 RPM
            break;
        case 'power':
            min = 0;
            max = 200; // 0-200W
            break;
        case 'voltage':
            min = 0;
            max = 15; // 0-15V
            break;
        case 'frequency':
        case 'clock':
            min = 0;
            max = 6000; // 0-6000 MHz
            break;
        default:
            min = 0;
            max = 100;
    }
    
    // Calculer le pourcentage
    const percentage = Math.min(Math.max((value - min) / (max - min), 0), 1);
    
    // Couleur selon le type et la valeur
    let color;
    if (sensorType === 'temperature') {
        if (value < 40) color = '#4a9eff'; // Bleu (froid)
        else if (value < 70) color = '#ff9800'; // Orange (tiède)
        else color = '#f44336'; // Rouge (chaud)
    } else if (sensorType === 'percentage' || sensorType === 'load') {
        if (value < 50) color = '#4caf50'; // Vert
        else if (value < 80) color = '#ff9800'; // Orange
        else color = '#f44336'; // Rouge
    } else if (sensorType === 'fan') {
        color = '#4caf50'; // Vert
    } else if (sensorType === 'power') {
        color = '#f44336'; // Rouge
    } else if (sensorType === 'voltage') {
        color = '#9c27b0'; // Violet
    } else if (sensorType === 'frequency' || sensorType === 'clock') {
        color = '#ffc107'; // Jaune
    } else {
        color = '#4a9eff'; // Bleu par défaut
    }
    
    // Effacer le canvas
    ctx.clearRect(0, 0, size, size);
    
    // Centre et rayon
    const centerX = size / 2;
    const centerY = size / 2;
    const radius = Math.max(size / 2 - 10, 5); // Minimum 5px de rayon
    const lineWidth = Math.max(size / 10, 2); // Minimum 2px d'épaisseur
    
    // Fond de la jauge (gris)
    ctx.beginPath();
    ctx.arc(centerX, centerY, radius, 0.75 * Math.PI, 2.25 * Math.PI);
    ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)';
    ctx.lineWidth = lineWidth;
    ctx.lineCap = 'round';
    ctx.stroke();
    
    // Arc de la valeur
    const startAngle = 0.75 * Math.PI;
    const endAngle = startAngle + (1.5 * Math.PI * percentage);
    
    ctx.beginPath();
    ctx.arc(centerX, centerY, radius, startAngle, endAngle);
    ctx.strokeStyle = color;
    ctx.lineWidth = lineWidth;
    ctx.lineCap = 'round';
    ctx.stroke();
    
    // Récupérer les options personnalisées
    const gaugeOptions = sensor.gauge_options || {};
    const showValue = gaugeOptions.show_value !== false; // true par défaut
    
    // Texte de la valeur au centre (si activé)
    if (showValue) {
        ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
        ctx.font = `bold ${size / 4}px -apple-system, sans-serif`;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillText(sensor.value, centerX, centerY);
    }
}

// === Applications ===
function renderApps() {
    const appsSection = document.getElementById('apps-section');
    
    if (!config || !config.apps || config.apps.length === 0) {
        if (appsSection) appsSection.style.display = 'none';
        cleanAppsFromTabs();
        appsRendered = false;
        return;
    }
    
    const appsTabId = config.apps_tab || '';
    
    // Si les apps ont déjà été rendues dans le même onglet, ne pas re-rendre
    if (appsRendered && lastAppsTabId === appsTabId) {
        return;
    }
    
    // Créer le HTML des boutons d'apps
    const appsHtml = config.apps.map((app, index) => `
        <button class="app-button" data-app-index="${index}">
            <div class="app-icon">${app.icon || '🚀'}</div>
            <div class="app-name">${app.name}</div>
        </button>
    `).join('');
    
    // Nettoyer d'abord les apps existantes dans les onglets
    cleanAppsFromTabs();
    
    // Si un onglet est spécifié, mettre les apps dans cet onglet
    if (appsTabId) {
        // Cacher la section séparée
        if (appsSection) appsSection.style.display = 'none';
        
        // Trouver le pane cible
        const targetPane = document.getElementById(`pane-${appsTabId}`);
        if (targetPane) {
            // Créer la nouvelle grille d'apps
            const appsContainer = document.createElement('div');
            appsContainer.className = 'apps-section-in-tab';
            appsContainer.innerHTML = `
                <h3 class="apps-title-in-tab">🚀 Applications</h3>
                <div class="apps-grid apps-grid-in-tab">${appsHtml}</div>
            `;
            
            // Ajouter à la fin du pane
            targetPane.appendChild(appsContainer);
            
            // Ajouter les event listeners
            appsContainer.querySelectorAll('.app-button').forEach(btn => {
                btn.addEventListener('click', () => launchApp(parseInt(btn.dataset.appIndex)));
            });
            
            appsRendered = true;
            lastAppsTabId = appsTabId;
        } else {
            // L'onglet cible n'existe pas encore, afficher dans la section séparée
            console.warn(`Onglet apps "${appsTabId}" non trouvé, affichage en section séparée`);
            renderAppsInSection(appsHtml);
            appsRendered = true;
            lastAppsTabId = '';
        }
    } else {
        // Afficher dans la section séparée (comportement par défaut)
        renderAppsInSection(appsHtml);
        appsRendered = true;
        lastAppsTabId = '';
    }
}

function renderAppsInSection(appsHtml) {
    const appsSection = document.getElementById('apps-section');
    const appsGrid = document.getElementById('apps-grid');
    
    if (appsSection && appsGrid) {
        appsSection.style.display = 'block';
        appsGrid.innerHTML = appsHtml;
        
        // Ajouter les event listeners
        appsGrid.querySelectorAll('.app-button').forEach(btn => {
            btn.addEventListener('click', () => launchApp(parseInt(btn.dataset.appIndex)));
        });
    }
}

// Nettoyer les apps des onglets (appelé lors du re-render)
function cleanAppsFromTabs() {
    document.querySelectorAll('.apps-section-in-tab').forEach(el => el.remove());
}

async function launchApp(appId) {
    try {
        const response = await fetch(`/api/apps/launch/${appId}`, {
            method: 'POST'
        });
        
        const result = await response.json();
        
        if (!result.success) {
            alert('Erreur: ' + result.error);
        }
        
    } catch (error) {
        console.error('Erreur lancement app:', error);
        alert('Erreur de lancement');
    }
}

// === Utilitaires ===
function updateTimestamp() {
    const now = new Date();
    const timeStr = now.toLocaleTimeString('fr-FR', {
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit'
    });
    
    document.getElementById('last-update').textContent = `🔄 ${timeStr}`;
}

function showError(message) {
    const errorState = document.getElementById('error-state');
    const errorMessage = document.getElementById('error-message');
    
    errorMessage.textContent = message;
    errorState.style.display = 'block';
    
    document.getElementById('empty-state').style.display = 'none';
    document.getElementById('tabs-nav').style.display = 'none';
    document.getElementById('tabs-content').style.display = 'none';
}

// Nettoyage à la fermeture
window.addEventListener('beforeunload', () => {
    if (updateInterval) {
        clearInterval(updateInterval);
    }
    
    charts.forEach((chart, key) => {
        // Chart.js a une méthode destroy, les jauges n'en ont pas
        if (chart && typeof chart.destroy === 'function') {
            chart.destroy();
        }
    });
});

// === Swipe Gestures ===
function initSwipeGestures() {
    const tabsContent = document.getElementById('tabs-content');
    
    if (!tabsContent) return;
    
    // Touch events
    tabsContent.addEventListener('touchstart', handleTouchStart, { passive: true });
    tabsContent.addEventListener('touchend', handleTouchEnd, { passive: true });
    
    // Optionnel: support souris pour test sur desktop
    tabsContent.addEventListener('mousedown', handleMouseDown);
    tabsContent.addEventListener('mouseup', handleMouseUp);
}

function handleTouchStart(e) {
    touchStartX = e.changedTouches[0].screenX;
    touchStartY = e.changedTouches[0].screenY;
}

function handleTouchEnd(e) {
    touchEndX = e.changedTouches[0].screenX;
    touchEndY = e.changedTouches[0].screenY;
    handleSwipe();
}

function handleMouseDown(e) {
    touchStartX = e.screenX;
    touchStartY = e.screenY;
}

function handleMouseUp(e) {
    touchEndX = e.screenX;
    touchEndY = e.screenY;
    handleSwipe();
}

function handleSwipe() {
    const deltaX = touchEndX - touchStartX;
    const deltaY = touchEndY - touchStartY;
    
    // Vérifier que c'est bien un swipe horizontal (pas vertical)
    if (Math.abs(deltaX) < SWIPE_THRESHOLD) return;
    if (Math.abs(deltaY) > Math.abs(deltaX)) return; // Scroll vertical, ignorer
    
    if (deltaX > 0) {
        // Swipe vers la droite → onglet précédent
        navigateToPreviousTab();
    } else {
        // Swipe vers la gauche → onglet suivant
        navigateToNextTab();
    }
}

function navigateToNextTab() {
    if (totalTabs <= 1) return;
    
    const nextIndex = (currentTabIndex + 1) % totalTabs;
    switchTabByIndex(nextIndex);
    
    // Feedback visuel
    showSwipeFeedback('next');
}

function navigateToPreviousTab() {
    if (totalTabs <= 1) return;
    
    const prevIndex = (currentTabIndex - 1 + totalTabs) % totalTabs;
    switchTabByIndex(prevIndex);
    
    // Feedback visuel
    showSwipeFeedback('prev');
}

function showSwipeFeedback(direction) {
    const content = document.getElementById('tabs-content');
    content.classList.add('swipe-' + direction);
    
    setTimeout(() => {
        content.classList.remove('swipe-' + direction);
    }, 200);
}
