/**
 * Gestion de l'XP vocal
 * Gain d'XP toutes les 10 minutes en vocal (5-25 XP)
 * - Timer ne démarre QUE si au moins 2 personnes dans le salon
 * - Timer s'arrête si l'utilisateur est mute/deafen
 * - totalVoiceTime est incrémenté chaque minute
 */

const { Events, EmbedBuilder } = require('discord.js');
const db = require('../functions/database/db.js');
const { addXP, getXPMultiplier, getXPProgress } = require('../functions/xp/xp.js');
const { colors } = require('../utils/constants');

// Map<guildId_userId, { xpInterval, timeInterval }>
const voiceUsers = new Map();

function canGainXP(member) {
    if (!member || !member.voice.channelId) return false;
    const voiceChannel = member.voice.channel;
    if (!voiceChannel) return false;

    // Compter les humains
    const membersInChannel = voiceChannel.members.filter(m => !m.user.bot).size;
    
    // Conditions : Pas tout seul, pas mute, pas deaf
    const isAlone = membersInChannel < 2;
    const isMuted = member.voice.serverMute || member.voice.selfMute;
    const isDeafened = member.voice.serverDeaf || member.voice.selfDeaf;

    return !isAlone && !isMuted && !isDeafened;
}

async function startTimers(key, member, guildId, userId) {
    // Si déjà des timers, on ne fait rien
    if (voiceUsers.has(key)) return;

    // 1. Timer XP (10 min)
    const xpInterval = setInterval(async () => {
        try {
            // Re-vérification dynamique
            const currentMember = await member.guild.members.fetch(userId).catch(() => null);
            if (!currentMember || !canGainXP(currentMember)) return;

            const multiplier = getXPMultiplier(currentMember, 'voice');
            const xpGained = Math.floor(Math.random() * 21) + 5; // 5-25 XP
            const result = await addXP(userId, guildId, xpGained, 'voice', multiplier);

            if (result && result.levelUp) {
                const progress = getXPProgress(result.newXP, result.newLevel);
                const embed = new EmbedBuilder()
                    .setTitle('🎉 Level Up !')
                    .setDescription(`Félicitations ${currentMember.toString()} ! Tu as atteint le niveau **${result.newLevel}** en vocal !`)
                    .setColor(colors.success)
                    .addFields(
                        { name: '📊 XP', value: `${result.newXP} XP`, inline: true },
                        { name: '⭐ Niveau', value: `${result.newLevel}`, inline: true },
                        { name: '📈 Progression', value: `${progress.current}/${progress.needed} XP (${progress.percentage}%)`, inline: true }
                    )
                    .setThumbnail(currentMember.user.displayAvatarURL({ dynamic: true }))
                    .setTimestamp();

                const systemChannel = member.guild.systemChannel;
                if (systemChannel) await systemChannel.send({ embeds: [embed] }).catch(() => null);
            }
        } catch (err) { console.error('Erreur Timer XP:', err); }
    }, 10 * 60 * 1000);

    // 2. Timer Temps (1 min)
    const timeInterval = setInterval(async () => {
        try {
            const currentMember = await member.guild.members.fetch(userId).catch(() => null);
            if (currentMember && canGainXP(currentMember)) {
                await db.query('UPDATE user_xp SET totalVoiceTime = totalVoiceTime + 1 WHERE userId = ? AND guildId = ?', [userId, guildId]);
            }
        } catch (err) { console.error('Erreur Timer Temps:', err); }
    }, 60 * 1000);

    voiceUsers.set(key, { xpInterval, timeInterval });
    
    // Mise à jour lastVoiceJoin
    await db.query('UPDATE user_xp SET lastVoiceJoin = ? WHERE userId = ? AND guildId = ?', [Date.now(), userId, guildId]).catch(() => {});
}

function stopTimers(key) {
    const userData = voiceUsers.get(key);
    if (userData) {
        clearInterval(userData.xpInterval);
        clearInterval(userData.timeInterval);
        voiceUsers.delete(key);
    }
}

async function updateState(member) {
    if (!member || member.user.bot) return;
    
    const guildId = member.guild.id;
    const userId = member.id;
    const key = `${guildId}_${userId}`;

    if (canGainXP(member)) {
        await startTimers(key, member, guildId, userId);
    } else {
        stopTimers(key);
    }
}

async function checkChannel(channel) {
    if (!channel) return;
    // Vérifier tous les membres du salon car l'arrivée/départ de quelqu'un change le statut "isAlone"
    for (const [id, member] of channel.members) {
        await updateState(member);
    }
}

module.exports = {
    name: Events.VoiceStateUpdate,
    async execute(oldState, newState) {
        try {
            // Cas 1: Join
            if (!oldState.channelId && newState.channelId) {
                await checkChannel(newState.channel);
            }
            // Cas 2: Leave
            else if (oldState.channelId && !newState.channelId) {
                const member = oldState.member;
                const key = `${member.guild.id}_${member.id}`;
                stopTimers(key); // Arrêt immédiat pour celui qui part
                await checkChannel(oldState.channel); // Vérif pour ceux qui restent
            }
            // Cas 3: Move
            else if (oldState.channelId && newState.channelId && oldState.channelId !== newState.channelId) {
                await checkChannel(oldState.channel);
                await checkChannel(newState.channel);
            }
            // Cas 4: Mute/Deaf update (Même channel)
            else if (oldState.channelId === newState.channelId) {
                await updateState(newState.member);
            }
        } catch (err) {
            console.error('Erreur VoiceStateUpdate:', err);
        }
    },
};