/**
 * Fonctions utilitaires pour le système XP
 */

const db = require('../database/db.js');

// Formule de calcul de l'XP nécessaire pour atteindre un niveau
function getXPForLevel(level) {
    if (level <= 0) return 0;
    return Math.floor(5 * Math.pow(level, 2) + 50 * level + 100);
}

// Calculer le niveau à partir de l'XP total
function getLevelFromXP(xp) {
    if (xp < 0) return 0;
    
    let level = 0;
    let requiredXP = getXPForLevel(level + 1);
    
    while (xp >= requiredXP) {
        level++;
        requiredXP = getXPForLevel(level + 1);
    }
    
    return level;
}

// Calculer l'XP nécessaire pour le prochain niveau
function getXPForNextLevel(level) {
    return getXPForLevel(level + 1);
}

// Calculer l'XP progress dans le niveau actuel
function getXPProgress(xp, level) {
    const xpForCurrentLevel = getXPForLevel(level);
    const xpForNextLevel = getXPForLevel(level + 1);
    
    const xpInLevel = Math.max(0, xp - xpForCurrentLevel);
    const xpNeeded = xpForNextLevel - xpForCurrentLevel;
    
    if (xpNeeded <= 0) {
        return { current: xpInLevel, needed: 100, percentage: 0 };
    }
    
    const percentage = Math.max(0, Math.min(100, Math.floor((xpInLevel / xpNeeded) * 100)));
    
    return { current: xpInLevel, needed: xpNeeded, percentage };
}

// Obtenir ou créer un utilisateur dans la table XP
async function getUserXP(userId, guildId) {
    try {
        const [rows] = await db.query(
            'SELECT * FROM user_xp WHERE userId = ? AND guildId = ?',
            [userId, guildId]
        );
        
        if (rows.length === 0) {
            await db.query(
                'INSERT INTO user_xp (userId, guildId, xp, level) VALUES (?, ?, 0, 0)',
                [userId, guildId]
            );
            return {
                userId, guildId, xp: 0, level: 0,
                lastMessageTime: 0, totalMessages: 0,
                totalVoiceTime: 0, lastVoiceJoin: 0, lastBumpTime: 0
            };
        }
        
        return rows[0];
    } catch (err) {
        console.error('Erreur getUserXP:', err);
        return null;
    }
}

// Ajouter de l'XP à un utilisateur
async function addXP(userId, guildId, xpGained, source = 'message', multiplier = 1.0) {
    try {
        const userXP = await getUserXP(userId, guildId);
        if (!userXP) return null;
        
        const finalXP = Math.floor(xpGained * multiplier);
        const newXP = userXP.xp + finalXP;
        const newLevel = getLevelFromXP(newXP);
        
        await db.query(
            'UPDATE user_xp SET xp = ?, level = ? WHERE userId = ? AND guildId = ?',
            [newXP, newLevel, userId, guildId]
        );
        
        try {
            await db.query(
                'INSERT INTO xp_logs (userId, guildId, xpGained, source, multiplier, timestamp) VALUES (?, ?, ?, ?, ?, ?)',
                [userId, guildId, finalXP, source, multiplier, Date.now()]
            );
        } catch {}
        
        return {
            oldXP: userXP.xp,
            newXP,
            oldLevel: userXP.level,
            newLevel,
            xpGained: finalXP,
            levelUp: newLevel > userXP.level
        };
    } catch (err) {
        console.error('Erreur addXP:', err);
        return null;
    }
}

// Vérifier si un salon est exclus de l'XP
async function isChannelExcluded(channelId, guildId) {
    try {
        const [rows] = await db.query(
            'SELECT * FROM xp_excluded_channels WHERE channelId = ? AND guildId = ?',
            [channelId, guildId]
        );
        return rows.length > 0;
    } catch (err) {
        console.error('Erreur isChannelExcluded:', err);
        return false;
    }
}

// Obtenir le multiplicateur XP d'un utilisateur
function getXPMultiplier(member, source = 'message') {
    let multiplier = 1.0;
    if (member.premiumSince) multiplier *= 1.2;
    return multiplier;
}

// Obtenir le classement des utilisateurs par XP
async function getLeaderboard(guildId, limit = 10) {
    try {
        const [rows] = await db.query(
            'SELECT * FROM user_xp WHERE guildId = ? ORDER BY xp DESC LIMIT ?',
            [guildId, limit]
        );
        return rows;
    } catch (err) {
        console.error('Erreur getLeaderboard:', err);
        return [];
    }
}

// Obtenir la position d'un utilisateur dans le classement
async function getUserRank(userId, guildId) {
    try {
        const userXP = await getUserXP(userId, guildId);
        if (!userXP) return 0;
        
        const [rows] = await db.query(
            'SELECT COUNT(*) as count FROM user_xp WHERE guildId = ? AND xp > ?',
            [guildId, userXP.xp]
        );
        
        return (rows[0]?.count || 0) + 1;
    } catch (err) {
        console.error('Erreur getUserRank:', err);
        return 0;
    }
}

module.exports = {
    getXPForLevel,
    getLevelFromXP,
    getXPForNextLevel,
    getXPProgress,
    getUserXP,
    addXP,
    isChannelExcluded,
    getXPMultiplier,
    getLeaderboard,
    getUserRank,
};