/**
 * FavMasToKey - Mode Filou (script de gestion des tokens multiples)
 */

// Attendre que le DOM soit chargé
document.addEventListener('DOMContentLoaded', function() {
    // Éléments DOM
    const uploadForm = document.getElementById('upload-form');
    const jsonFileInput = document.getElementById('json-file');
    const fileSummary = document.getElementById('file-summary');
    const startMigration = document.getElementById('start-migration');
    const pauseMigration = document.getElementById('pause-migration');
    const cancelMigration = document.getElementById('cancel-migration');
    const globalProgress = document.getElementById('global-progress');
    const successProgress = document.getElementById('success-progress');
    const skipProgress = document.getElementById('skip-progress');
    const warnProgress = document.getElementById('warn-progress');
    const errorProgress = document.getElementById('error-progress');
    const operationLog = document.getElementById('operation-log');
    const clearLog = document.getElementById('clear-log');
    const statsDisplay = document.getElementById('stats-display');
    
    // Sliders de configuration
    const delayBetweenTokens = document.getElementById('delay-between-tokens');
    const tokenCooldown = document.getElementById('token-cooldown');
    const delayValue = document.getElementById('delay-value');
    const cooldownValue = document.getElementById('cooldown-value');
    const autoAdjust = document.getElementById('auto-adjust');
    
    // Variables globales
    let favoritesList = [];
    let currentIndex = 0;
    let totalItems = 0;
    let isProcessing = false;
    let isPaused = false;
    let successCount = 0;
    let errorCount = 0;
    let skippedCount = 0;
    let warningCount = 0;
    
    // Variables pour la gestion des tokens
    let tokens = [];
    let tokensQueue = [];
    let currentTokenIndex = 0;
    let tokenTimers = {};
    let activeRequests = 0;
    let maxConcurrentRequests = 1; // Pour éviter les problèmes de race condition
    
    // Options de migration
    let migration = {
        status: 'not_started',
        startTime: null,
        lastUpdateTime: null,
        progress: {
            current: 0,
            total: 0,
            percentage: 0
        },
        stats: {
            success: 0,
            error: 0,
            skipped: 0,
            warning: 0
        },
        options: {
            delayBetweenTokens: 15,  // secondes
            tokenCooldown: 150,     // secondes
            autoAdjust: true
        }
    };
    
    // ---- Gestionnaire d'événements ----
    
    // Gérer les changements sur les sliders
    if (delayBetweenTokens && delayValue) {
        delayBetweenTokens.addEventListener('input', function() {
            delayValue.textContent = this.value + 's';
            migration.options.delayBetweenTokens = parseInt(this.value);
            updateLocalStorage();
        });
    }
    
    if (tokenCooldown && cooldownValue) {
        tokenCooldown.addEventListener('input', function() {
            cooldownValue.textContent = this.value + 's';
            migration.options.tokenCooldown = parseInt(this.value);
            updateLocalStorage();
        });
    }
    
    if (autoAdjust) {
        autoAdjust.addEventListener('change', function() {
            migration.options.autoAdjust = this.checked;
            updateLocalStorage();
        });
    }
    
    // Gérer le téléchargement et l'analyse du fichier JSON
    if (uploadForm) {
        uploadForm.addEventListener('submit', function(e) {
            e.preventDefault();
            
            const file = jsonFileInput.files[0];
            if (!file) {
                alert('Veuillez sélectionner un fichier JSON.');
                return;
            }
            
            // Vérifier l'extension du fichier
            if (!file.name.endsWith('.json')) {
                alert('Le fichier doit être au format JSON.');
                return;
            }
            
            // Lire le fichier
            const reader = new FileReader();
            reader.onload = function(event) {
                try {
                    const json = JSON.parse(event.target.result);
                    
                    // Vérifier la structure du fichier
                    if (!json['@context'] || !json.type || !json.orderedItems) {
                        alert('Le format du fichier JSON n\'est pas celui attendu pour un export de favoris Mastodon.');
                        return;
                    }
                    
                    favoritesList = json.orderedItems;
                    totalItems = favoritesList.length;
                    
                    // Afficher un résumé
                    fileSummary.classList.remove('d-none');
                    fileSummary.innerHTML = `
                        <strong>${totalItems}</strong> favoris trouvés dans votre fichier Mastodon.
                        Le transfert sera effectué avec les jetons configurés.
                    `;
                    
                    // Stocker les données dans localStorage pour les conserver
                    localStorage.setItem('favmastokey_favorites', JSON.stringify(favoritesList));
                    
                    // Initialiser les données de migration
                    migration = {
                        status: 'not_started',
                        startTime: null,
                        lastUpdateTime: null,
                        progress: {
                            current: 0,
                            total: totalItems,
                            percentage: 0
                        },
                        stats: {
                            success: 0,
                            error: 0,
                            skipped: 0,
                            warning: 0
                        },
                        options: {
                            delayBetweenTokens: parseInt(delayBetweenTokens ? delayBetweenTokens.value : 15),
                            tokenCooldown: parseInt(tokenCooldown ? tokenCooldown.value : 150),
                            autoAdjust: autoAdjust ? autoAdjust.checked : true
                        }
                    };
                    
                    // Sauvegarder les données de migration
                    updateLocalStorage();
                    
                    // Scroll jusqu'à la section de migration
                    document.getElementById('step3').scrollIntoView({ behavior: 'smooth' });
                    
                } catch (error) {
                    alert('Erreur lors de l\'analyse du fichier JSON: ' + error.message);
                }
            };
            
            reader.onerror = function() {
                alert('Erreur lors de la lecture du fichier.');
            };
            
            reader.readAsText(file);
        });
    }
    
    // Effacer le journal des opérations
    if (clearLog) {
        clearLog.addEventListener('click', function() {
            operationLog.innerHTML = '';
        });
    }
    
    // Démarrer la migration
    if (startMigration) {
        startMigration.addEventListener('click', function() {
            if (isProcessing) return;
            
            // Récupérer les favoris du localStorage si nécessaire
            if (favoritesList.length === 0 && localStorage.getItem('favmastokey_favorites')) {
                favoritesList = JSON.parse(localStorage.getItem('favmastokey_favorites'));
                totalItems = favoritesList.length;
            }
            
            if (favoritesList.length === 0) {
                addLogEntry('Aucun favori à migrer. Veuillez d\'abord télécharger votre fichier JSON.', 'error');
                return;
            }
            
            // Vérifier s'il y a une migration en cours à reprendre
            if (localStorage.getItem('favmastokey_multitoken_migration')) {
                const savedMigration = JSON.parse(localStorage.getItem('favmastokey_multitoken_migration'));
                
                // Si la migration était en cours ou en pause, proposer de la reprendre
                if (savedMigration.status === 'in_progress' || savedMigration.status === 'paused') {
                    const resumeConfirm = confirm(`Une migration précédente a été trouvée (${savedMigration.progress.percentage.toFixed(1)}% terminée). Voulez-vous la reprendre?`);
                    
                    if (resumeConfirm) {
                        // Restaurer l'état de la migration
                        migration = savedMigration;
                        currentIndex = migration.progress.current;
                        
                        // Restaurer les statistiques
                        successCount = migration.stats.success || 0;
                        errorCount = migration.stats.error || 0;
                        skippedCount = migration.stats.skipped || 0;
                        warningCount = migration.stats.warning || 0;
                        
                        // Mettre à jour l'interface
                        updateProgress(migration.progress.percentage);
                        updateStatistics();
                    } else {
                        // Réinitialiser la migration
                        resetMigration();
                    }
                } else {
                    // Réinitialiser la migration
                    resetMigration();
                }
            } else {
                // Initialiser une nouvelle migration
                resetMigration();
            }
            
            // Initialiser les tokens
            initializeTokens();
            
            if (tokens.length === 0) {
                addLogEntry('Aucun jeton d\'accès disponible. Veuillez configurer au moins un jeton.', 'error');
                return;
            }
            
            // Démarrer la migration
            isProcessing = true;
            isPaused = false;
            
            startMigration.classList.add('d-none');
            pauseMigration.classList.remove('d-none');
            
            // Initialiser le temps de démarrage si c'est une nouvelle migration
            if (migration.status === 'not_started' || migration.startTime === null) {
                migration.startTime = Date.now();
            }
            
            // Mettre à jour le statut de la migration
            migration.status = 'in_progress';
            updateLocalStorage();
            
            // Afficher un message de démarrage
            const tokenCountMsg = tokens.length === 1 ? '1 jeton' : `${tokens.length} jetons`;
            addLogEntry(`Démarrage de la migration avec ${tokenCountMsg}. Délai entre jetons: ${migration.options.delayBetweenTokens}s, Délai de récupération: ${migration.options.tokenCooldown}s`, 'info');
            
            // Lancer le processus de migration
            startTokenRotation();
        });
    }
    
    // Gérer la pause de la migration
    if (pauseMigration) {
        pauseMigration.addEventListener('click', function() {
            if (!isProcessing) return;
            
            isPaused = !isPaused;
            
            if (isPaused) {
                pauseMigration.textContent = 'Reprendre';
                addLogEntry('Migration en pause.', 'warning');
                
                // Mettre à jour le statut de la migration
                migration.status = 'paused';
                updateLocalStorage();
            } else {
                pauseMigration.textContent = 'Pause';
                addLogEntry('Reprise de la migration...', 'info');
                
                // Mettre à jour le statut de la migration
                migration.status = 'in_progress';
                updateLocalStorage();
                
                // Reprendre le traitement
                startTokenRotation();
            }
        });
    }
    
    // Gérer l'annulation de la migration
    if (cancelMigration) {
        cancelMigration.addEventListener('click', function() {
            if (!isProcessing && currentIndex === 0) return;
            
            const confirmCancel = confirm('Êtes-vous sûr de vouloir annuler la migration en cours ?');
            if (confirmCancel) {
                isProcessing = false;
                isPaused = false;
                
                addLogEntry('Migration annulée.', 'error');
                
                // Nettoyer les timers
                clearAllTimers();
                
                // Réinitialiser l'interface
                startMigration.classList.remove('d-none');
                pauseMigration.classList.add('d-none');
                pauseMigration.textContent = 'Pause';
                
                // Réinitialiser les tokens
                resetTokensStatus();
                
                // Réinitialiser les données de migration
                resetMigration();
            }
        });
    }
    
    // Vérifier si nous avons des données à restaurer au chargement
    function initOnLoad() {
        // Récupérer les favoris du localStorage
        if (localStorage.getItem('favmastokey_favorites')) {
            favoritesList = JSON.parse(localStorage.getItem('favmastokey_favorites'));
            totalItems = favoritesList.length;
            
            if (fileSummary) {
                fileSummary.classList.remove('d-none');
                fileSummary.innerHTML = `
                    <strong>${totalItems}</strong> favoris trouvés dans votre fichier Mastodon.
                    Le transfert sera effectué avec les jetons configurés.
                `;
            }
        }
        
        // Récupérer les données de migration
        if (localStorage.getItem('favmastokey_multitoken_migration')) {
            migration = JSON.parse(localStorage.getItem('favmastokey_multitoken_migration'));
            currentIndex = migration.progress.current;
            
            successCount = migration.stats.success || 0;
            errorCount = migration.stats.error || 0;
            skippedCount = migration.stats.skipped || 0;
            warningCount = migration.stats.warning || 0;
            
            // Mettre à jour l'interface
            updateProgress(migration.progress.percentage);
            updateStatistics();
            
            // Restaurer les options
            if (migration.options) {
                if (delayBetweenTokens && migration.options.delayBetweenTokens) {
                    delayBetweenTokens.value = migration.options.delayBetweenTokens;
                    if (delayValue) {
                        delayValue.textContent = migration.options.delayBetweenTokens + 's';
                    }
                }
                
                if (tokenCooldown && migration.options.tokenCooldown) {
                    tokenCooldown.value = migration.options.tokenCooldown;
                    if (cooldownValue) {
                        cooldownValue.textContent = migration.options.tokenCooldown + 's';
                    }
                }
                
                if (autoAdjust && migration.options.autoAdjust !== undefined) {
                    autoAdjust.checked = migration.options.autoAdjust;
                }
            }
            
            // Si la migration était en cours, proposer de la reprendre
            if ((migration.status === 'in_progress' || migration.status === 'paused') && 
                migration.progress.current < migration.progress.total) {
                
                const timeAgo = getTimeAgoString(new Date(migration.lastUpdateTime));
                
                // Ajouter une entrée au journal
                addLogEntry(`Une migration précédente a été trouvée (${migration.progress.percentage.toFixed(1)}% terminée, ${timeAgo}). Utilisez le bouton "Démarrer la migration" pour la reprendre.`, 'info');
            }
        }
    }
    
    // Initialiser les tokens à partir des éléments du DOM
    function initializeTokens() {
        tokens = [];
        tokensQueue = [];
        
        // Ajouter le token principal
        tokens.push({
            id: 'primary',
            name: 'Token principal',
            status: 'ready',
            lastUsed: null,
            cooldownUntil: null,
            errorCount: 0,
            element: document.querySelector('.token-card:first-child')
        });
        
        // Ajouter les tokens supplémentaires
        const tokenCards = document.querySelectorAll('.token-card[data-token-id]');
        tokenCards.forEach(card => {
            const tokenId = card.getAttribute('data-token-id');
            tokens.push({
                id: tokenId,
                name: card.querySelector('strong').textContent,
                status: 'ready',
                lastUsed: null,
                cooldownUntil: null,
                errorCount: 0,
                element: card
            });
        });
        
        // Initialiser la file d'attente avec tous les tokens
        resetTokensQueue();
    }
    
    // Réinitialiser la file d'attente des tokens
    function resetTokensQueue() {
        tokensQueue = [...tokens]; // Copie de tous les tokens
        
        // Mélanger pour éviter d'utiliser toujours le même ordre
        shuffleArray(tokensQueue);
    }
    
    // Mélanger un tableau (algorithme de Fisher-Yates)
    function shuffleArray(array) {
        for (let i = array.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [array[i], array[j]] = [array[j], array[i]];
        }
        return array;
    }
    
    // Démarrer la rotation des tokens
    function startTokenRotation() {
        if (!isProcessing || isPaused) {
            return;
        }
        
        // Vérifier si nous avons terminé
        if (currentIndex >= totalItems) {
            finishMigration();
            return;
        }
        
        // Si la file d'attente est vide, la réinitialiser
        if (tokensQueue.length === 0) {
            resetTokensQueue();
        }
        
        // Vérifier si on a un token disponible
        const availableToken = findAvailableToken();
        
        if (availableToken) {
            // Traiter le prochain favori avec ce token
            processWithToken(availableToken);
        } else {
            // Aucun token disponible actuellement, attendre et réessayer
            addLogEntry('Tous les jetons sont en cours d\'utilisation ou en récupération. Attente...', 'info');
            setTimeout(startTokenRotation, 5000);
        }
    }
    
    // Trouver un token disponible
    function findAvailableToken() {
        const now = Date.now();
        
        // Vérifier d'abord la file d'attente
        for (let i = 0; i < tokensQueue.length; i++) {
            const token = tokensQueue[i];
            
            // Vérifier si le token est prêt
            if (token.status === 'ready' && 
                (!token.cooldownUntil || now >= token.cooldownUntil)) {
                
                // Retirer ce token de la file d'attente
                tokensQueue.splice(i, 1);
                return token;
            }
        }
        
        // Si aucun token n'est disponible dans la file d'attente,
        // vérifier tous les tokens (au cas où un token aurait fini son cooldown)
        for (const token of tokens) {
            if (token.status === 'ready' && 
                (!token.cooldownUntil || now >= token.cooldownUntil)) {
                
                // Retirer ce token de la file d'attente s'il y est encore
                const queueIndex = tokensQueue.findIndex(t => t.id === token.id);
                if (queueIndex !== -1) {
                    tokensQueue.splice(queueIndex, 1);
                }
                
                return token;
            }
        }
        
        // Aucun token disponible
        return null;
    }
    
    // Traiter un favori avec un token spécifique
    function processWithToken(token) {
        if (!isProcessing || isPaused) {
            return;
        }
        
        // Mettre à jour le statut du token
        updateTokenStatus(token, 'active');
        
        // URL à traiter
        const url = favoritesList[currentIndex];
        
        // Ajouter une entrée dans le journal
        addLogEntry(`[${token.name}] Traitement de: ${getTruncatedUrl(url)}`, 'info');
        
        // Envoyer la requête au serveur
        fetch('process_multitoken.php', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                url: url,
                token_id: token.id,
                current_index: currentIndex,
                total_items: totalItems
            })
        })
        .then(response => response.json())
        .then(data => {
            // Mettre à jour les statistiques en fonction du résultat
            handleProcessResult(data, token, url);
            
            // Mettre à jour l'index
            currentIndex++;
            
            // Mettre à jour la progression
            updateProgress();
            
            // Mettre le token en cooldown
            const cooldownPeriod = migration.options.tokenCooldown * 1000; // Convertir en millisecondes
            const cooldownUntil = Date.now() + cooldownPeriod;
            
            token.lastUsed = Date.now();
            token.cooldownUntil = cooldownUntil;
            
            updateTokenStatus(token, 'cooldown');
            
            // Programmer la réactivation du token après le cooldown
            tokenTimers[token.id] = setTimeout(() => {
                // Remettre le token en état "prêt"
                updateTokenStatus(token, 'ready');
                
                // Ajouter le token à la fin de la file d'attente
                tokensQueue.push(token);
                
            }, cooldownPeriod);
            
            // Démarrer le traitement du prochain favori après un délai
            setTimeout(startTokenRotation, migration.options.delayBetweenTokens * 1000);
        })
        .catch(error => {
            console.error('Erreur lors du traitement:', error);
            
            // Ajouter l'erreur au journal
            addLogEntry(`[${token.name}] Erreur lors du traitement: ${error.message}`, 'error');
            
            // Incrémenter le compteur d'erreurs du token
            token.errorCount = (token.errorCount || 0) + 1;
            
            // Si trop d'erreurs avec ce token, le mettre en erreur
            if (token.errorCount >= 3) {
                updateTokenStatus(token, 'error');
                addLogEntry(`[${token.name}] Ce jeton rencontre des problèmes répétés et a été désactivé.`, 'error');
            } else {
                // Sinon, mettre le token en cooldown plus court
                const cooldownPeriod = 30 * 1000; // 30 secondes
                const cooldownUntil = Date.now() + cooldownPeriod;
                
                token.lastUsed = Date.now();
                token.cooldownUntil = cooldownUntil;
                
                updateTokenStatus(token, 'cooldown');
                
                // Programmer la réactivation du token après le cooldown
                tokenTimers[token.id] = setTimeout(() => {
                    updateTokenStatus(token, 'ready');
                    tokensQueue.push(token);
                }, cooldownPeriod);
            }
            
            // Augmenter le compteur d'erreurs
            errorCount++;
            updateStatistics();
            
            // Continuer avec le prochain token après un délai
            setTimeout(startTokenRotation, migration.options.delayBetweenTokens * 1000);
        });
    }
    
    // Gérer le résultat du traitement
    function handleProcessResult(data, token, url) {
        if (data.success) {
            // Résultat du traitement
            const result = data.result;
            
            // Construction du message avec détails si disponibles
            let message = result.message;
            if (result.details) {
                message += ` (${result.details})`;
            }
            
            // Ajouter l'entrée au journal avec le nom du token
            addLogEntry(`[${token.name}] ${message}`, result.status);
            
            // Mettre à jour les compteurs
            if (result.status === 'success') {
                successCount++;
                token.errorCount = 0; // Réinitialiser le compteur d'erreurs
            } else if (result.status === 'error') {
                errorCount++;
                
                // Incrémenter le compteur d'erreurs du token
                token.errorCount = (token.errorCount || 0) + 1;
                
                // Si autoAdjust est activé et qu'il y a beaucoup d'erreurs, augmenter les délais
                if (migration.options.autoAdjust && token.errorCount >= 2) {
                    if (result.error_type === 'rate_limit') {
                        // Augmenter le délai entre les tokens
                        if (migration.options.delayBetweenTokens < 60) {
                            migration.options.delayBetweenTokens += 5;
                            if (delayBetweenTokens) delayBetweenTokens.value = migration.options.delayBetweenTokens;
                            if (delayValue) delayValue.textContent = migration.options.delayBetweenTokens + 's';
                            
                            addLogEntry(`Délai entre jetons automatiquement augmenté à ${migration.options.delayBetweenTokens}s en raison de limitations d'API.`, 'warning');
                        }
                        
                        // Augmenter le délai de cooldown
                        if (migration.options.tokenCooldown < 300) {
                            migration.options.tokenCooldown += 30;
                            if (tokenCooldown) tokenCooldown.value = migration.options.tokenCooldown;
                            if (cooldownValue) cooldownValue.textContent = migration.options.tokenCooldown + 's';
                            
                            addLogEntry(`Délai de récupération automatiquement augmenté à ${migration.options.tokenCooldown}s.`, 'warning');
                        }
                        
                        // Mettre à jour le localStorage
                        updateLocalStorage();
                    }
                }
            } else if (result.status === 'info') {
                skippedCount++;
                token.errorCount = 0; // Réinitialiser le compteur d'erreurs
            } else if (result.status === 'warning') {
                warningCount++;
                
                // Si c'est une erreur de rate limit, incrémenter le compteur d'erreurs
                if (result.error_type === 'rate_limit') {
                    token.errorCount = (token.errorCount || 0) + 1;
                }
            }
            
            // Mettre à jour les statistiques
            updateStatistics();
        } else {
            // Erreur lors du traitement
            addLogEntry(`[${token.name}] Erreur: ${data.message}`, 'error');
            errorCount++;
            updateStatistics();
            
            // Incrémenter le compteur d'erreurs du token
            token.errorCount = (token.errorCount || 0) + 1;
        }
    }
    
    // Mettre à jour le statut d'un token
    function updateTokenStatus(token, status) {
        token.status = status;
        
        if (token.element) {
            // Mettre à jour la classe CSS
            token.element.classList.remove('active', 'cooldown', 'error');
            
            // Mettre à jour l'indicateur de statut
            const statusIndicator = token.element.querySelector('.token-status');
            const statusText = token.element.querySelector('.text-muted.small');
            
            if (statusIndicator) {
                statusIndicator.classList.remove('ready', 'cooldown', 'error', 'idle');
            }
            
            switch (status) {
                case 'active':
                    token.element.classList.add('active');
                    if (statusIndicator) statusIndicator.classList.add('ready');
                    if (statusText) statusText.textContent = 'En cours d\'utilisation';
                    break;
                    
                case 'cooldown':
                    token.element.classList.add('cooldown');
                    if (statusIndicator) statusIndicator.classList.add('cooldown');
                    
                    if (statusText && token.cooldownUntil) {
                        const cooldownSeconds = Math.ceil((token.cooldownUntil - Date.now()) / 1000);
                        statusText.textContent = `Récupération: ${cooldownSeconds}s`;
                        
                        // Mettre à jour le compteur de cooldown toutes les secondes
                        const updateInterval = setInterval(() => {
                            const remainingSeconds = Math.ceil((token.cooldownUntil - Date.now()) / 1000);
                            if (remainingSeconds <= 0) {
                                clearInterval(updateInterval);
                                if (statusText) statusText.textContent = 'Prêt';
                            } else {
                                if (statusText) statusText.textContent = `Récupération: ${remainingSeconds}s`;
                            }
                        }, 1000);
                    }
                    break;
                    
                case 'error':
                    token.element.classList.add('error');
                    if (statusIndicator) statusIndicator.classList.add('error');
                    if (statusText) statusText.textContent = 'Erreur';
                    break;
                    
                case 'ready':
                default:
                    if (statusIndicator) statusIndicator.classList.add('ready');
                    if (statusText) statusText.textContent = 'Prêt';
                    break;
            }
        }
    }
    
    // Réinitialiser le statut de tous les tokens
    function resetTokensStatus() {
        tokens.forEach(token => {
            updateTokenStatus(token, 'ready');
            token.lastUsed = null;
            token.cooldownUntil = null;
            token.errorCount = 0;
        });
    }
    
    // Nettoyer tous les timers
    function clearAllTimers() {
        Object.keys(tokenTimers).forEach(tokenId => {
            clearTimeout(tokenTimers[tokenId]);
            delete tokenTimers[tokenId];
        });
    }
    
    // Obtenir une version tronquée d'une URL pour l'affichage
    function getTruncatedUrl(url) {
        if (url.length <= 60) return url;
        
        const urlObj = new URL(url);
        const domain = urlObj.hostname;
        const path = urlObj.pathname;
        
        const lastSegment = path.split('/').pop();
        return `${domain}/.../${lastSegment}`;
    }
    
    // Générer une chaîne "il y a X minutes/heures" à partir d'une date
    function getTimeAgoString(date) {
        const now = new Date();
        const diffMs = now - date;
        const diffSeconds = Math.floor(diffMs / 1000);
        
        if (diffSeconds < 60) {
            return `il y a ${diffSeconds} seconde${diffSeconds > 1 ? 's' : ''}`;
        }
        
        const diffMinutes = Math.floor(diffSeconds / 60);
        if (diffMinutes < 60) {
            return `il y a ${diffMinutes} minute${diffMinutes > 1 ? 's' : ''}`;
        }
        
        const diffHours = Math.floor(diffMinutes / 60);
        if (diffHours < 24) {
            return `il y a ${diffHours} heure${diffHours > 1 ? 's' : ''}`;
        }
        
        const diffDays = Math.floor(diffHours / 24);
        return `il y a ${diffDays} jour${diffDays > 1 ? 's' : ''}`;
    }
    
    /**
     * Réinitialise les données de migration
     */
    function resetMigration() {
        currentIndex = 0;
        successCount = 0;
        errorCount = 0;
        skippedCount = 0;
        warningCount = 0;
        
        migration = {
            status: 'not_started',
            startTime: null,
            lastUpdateTime: null,
            progress: {
                current: 0,
                total: totalItems,
                percentage: 0
            },
            stats: {
                success: 0,
                error: 0,
                skipped: 0,
                warning: 0
            },
            options: {
                delayBetweenTokens: parseInt(delayBetweenTokens ? delayBetweenTokens.value : 15),
                tokenCooldown: parseInt(tokenCooldown ? tokenCooldown.value : 150),
                autoAdjust: autoAdjust ? autoAdjust.checked : true
            }
        };
        
        // Mettre à jour le localStorage
        updateLocalStorage();
        
        // Mettre à jour l'interface
        updateProgress(0);
        updateStatistics();
    }
    
    /**
     * Met à jour les données de migration dans localStorage
     */
    function updateLocalStorage() {
        migration.lastUpdateTime = Date.now();
        
        migration.progress = {
            current: currentIndex,
            total: totalItems,
            percentage: (currentIndex / totalItems) * 100
        };
        
        migration.stats = {
            success: successCount,
            error: errorCount,
            skipped: skippedCount,
            warning: warningCount
        };
        
        if (delayBetweenTokens && tokenCooldown && autoAdjust) {
            migration.options = {
                delayBetweenTokens: parseInt(delayBetweenTokens.value),
                tokenCooldown: parseInt(tokenCooldown.value),
                autoAdjust: autoAdjust.checked
            };
        }
        
        // Sauvegarder dans localStorage
        localStorage.setItem('favmastokey_multitoken_migration', JSON.stringify(migration));
    }
    
    /**
     * Terminer la migration avec succès
     */
    function finishMigration() {
        isProcessing = false;
        
        // Nettoyer les timers
        clearAllTimers();
        
        const summary = `Migration terminée ! ${successCount} publications ajoutées aux favoris, ${errorCount} échecs, ${skippedCount} déjà présentes, ${warningCount} avertissements.`;
        addLogEntry(summary, 'success');
        
        startMigration.classList.remove('d-none');
        startMigration.textContent = 'Terminer';
        
        startMigration.addEventListener('click', function onceFinished() {
            // Nettoyer localStorage
            localStorage.removeItem('favmastokey_multitoken_migration');
            
            // Ne pas supprimer les favoris pour permettre une nouvelle migration si nécessaire
            // localStorage.removeItem('favmastokey_favorites');
            
            // Réinitialiser l'interface
            resetTokensStatus();
            startMigration.textContent = 'Démarrer la migration';
            
            // Retirer cet écouteur d'événement pour éviter les doublons
            startMigration.removeEventListener('click', onceFinished);
            
            // Scroll vers le haut
            window.scrollTo({ top: 0, behavior: 'smooth' });
        });
        
        pauseMigration.classList.add('d-none');
        
        // Mettre à jour la progression à 100%
        updateProgress(100);
        
        // Mettre à jour le statut de la migration
        migration.status = 'completed';
        updateLocalStorage();
    }
    
    /**
     * Met à jour la barre de progression
     */
    function updateProgress(forcedValue = null) {
        const progress = forcedValue !== null ? forcedValue : (currentIndex / totalItems) * 100;
        
        if (globalProgress) {
            globalProgress.style.width = progress + '%';
            globalProgress.textContent = Math.round(progress) + '%';
            globalProgress.setAttribute('aria-valuenow', progress);
        }
        
        // Mettre à jour le localStorage
        updateLocalStorage();
    }
    
    /**
     * Met à jour les statistiques de progression
     */
    function updateStatistics() {
        // Calculer les pourcentages pour les barres de progression
        const total = successCount + errorCount + skippedCount + warningCount;
        const successPct = total > 0 ? (successCount / total) * 100 : 0;
        const skipPct = total > 0 ? (skippedCount / total) * 100 : 0;
        const warnPct = total > 0 ? (warningCount / total) * 100 : 0;
        const errorPct = total > 0 ? (errorCount / total) * 100 : 0;
        
        // Mettre à jour les barres
        if (successProgress) {
            successProgress.style.width = successPct + '%';
            successProgress.setAttribute('aria-valuenow', successPct);
        }
        
        if (skipProgress) {
            skipProgress.style.width = skipPct + '%';
            skipProgress.setAttribute('aria-valuenow', skipPct);
        }
        
        if (warnProgress) {
            warnProgress.style.width = warnPct + '%';
            warnProgress.setAttribute('aria-valuenow', warnPct);
        }
        
        if (errorProgress) {
            errorProgress.style.width = errorPct + '%';
            errorProgress.setAttribute('aria-valuenow', errorPct);
        }
        
        // Mettre à jour le texte des statistiques
        if (statsDisplay) {
            statsDisplay.textContent = `${successCount} succès, ${skippedCount} ignorés, ${warningCount} avertissements, ${errorCount} erreurs`;
        }
        
        // Mettre à jour le localStorage
        updateLocalStorage();
    }
    
    /**
     * Ajoute une entrée dans le journal des opérations
     */
    function addLogEntry(message, status = 'info') {
        if (!operationLog) return;
        
        const entry = document.createElement('div');
        entry.className = `log-entry ${status}`;
        
        const timestamp = new Date().toLocaleTimeString();
        entry.textContent = `[${timestamp}] ${message}`;
        
        operationLog.appendChild(entry);
        
        // Scroll vers le bas pour voir la dernière entrée
        const logContainer = document.getElementById('log-container');
        if (logContainer) {
            logContainer.scrollTop = logContainer.scrollHeight;
        }
    }
    
    // Initialiser la page au chargement
    initOnLoad();
});