// Load environment variables from .env file
require('dotenv').config();
const { Client, GatewayIntentBits, Collection } = require('discord.js');
const { Shoukaku, Connectors } = require('shoukaku');
const logger = require('./utils/logger');
const fs = require('fs');
const path = require('path');

// Validate essential environment variables
if (!process.env.DISCORD_TOKEN) {
    logger.error('DISCORD_TOKEN is missing in the .env file!');
    process.exit(1);
}
if (!process.env.LAVALINK_HOST || !process.env.LAVALINK_PORT || !process.env.LAVALINK_PASSWORD) {
    logger.warn('Lavalink connection details (HOST, PORT, PASSWORD) are missing or incomplete in .env. Music functionality will be limited.');
    // Decide if the bot should exit or continue without music
    // process.exit(1); // Uncomment to exit if Lavalink is mandatory
}

// Create a new Discord client instance with necessary intents
const client = new Client({
    intents: [
        GatewayIntentBits.Guilds,
        GatewayIntentBits.GuildVoiceStates,
        GatewayIntentBits.GuildMessages, // Add if needed for prefix commands or message content
        GatewayIntentBits.MessageContent, // Add if needed for message content
    ],
});

// Define Shoukaku nodes - fix the URL format to properly connect to Lavalink
const Nodes = [
    {
        name: 'lavalink',
        url: `${process.env.LAVALINK_HOST || 'localhost'}:${process.env.LAVALINK_PORT || '2333'}`,
        auth: process.env.LAVALINK_PASSWORD || 'youshallnotpass',
        secure: process.env.LAVALINK_SECURE === 'true'
    }
];

// Initialize Shoukaku with proper configuration
client.shoukaku = new Shoukaku(new Connectors.DiscordJS(client), Nodes, {
    moveOnDisconnect: false,
    resume: true,
    reconnectTries: 10,
    reconnectInterval: 5000,
});

// Show the actual Lavalink connection details (without exposing the actual password)
logger.info(`Lavalink connection configured to: ${process.env.LAVALINK_HOST}:${process.env.LAVALINK_PORT} (Password: ${process.env.LAVALINK_PASSWORD ? '[SET]' : '[NOT SET]'})`);

// Collections for commands
client.commands = new Collection();

// --- Command Loading ---
const commandsPath = path.join(__dirname, 'commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));

for (const file of commandFiles) {
    const filePath = path.join(commandsPath, file);
    try {
        const command = require(filePath);
        // Set a new item in the Collection with the key as the command name and the value as the exported module
        if ('data' in command && 'execute' in command) {
            client.commands.set(command.data.name, command);
            logger.info(`Loaded command: ${command.data.name}`);
        } else {
            logger.warn(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
        }
    } catch (error) {
        logger.error(`Error loading command at ${filePath}: ${error.message}`, error);
    }
}

// --- Event Handling ---
const eventsPath = path.join(__dirname, 'events');
const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js'));

for (const file of eventFiles) {
    const filePath = path.join(eventsPath, file);
    const event = require(filePath);
    if (event.once) {
        client.once(event.name, (...args) => event.execute(...args, client)); // Pass client to event handlers
        logger.info(`Loaded event ${event.name} (once)`);
    } else {
        client.on(event.name, (...args) => event.execute(...args, client)); // Pass client to event handlers
        logger.info(`Loaded event ${event.name}`);
    }
}

// --- Shoukaku Event Handling ---
// Set up Shoukaku event handlers
client.shoukaku.on('ready', (name) => logger.info(`Lavalink Node: ${name} is now connected`));
client.shoukaku.on('error', (name, error) => logger.error(`Lavalink Node: ${name} emitted an error: ${error.message}`));
client.shoukaku.on('close', (name, code, reason) => logger.warn(`Lavalink Node: ${name} closed with code ${code}. Reason: ${reason || 'No reason'}`));
client.shoukaku.on('disconnect', (name, reason) => logger.warn(`Lavalink Node: ${name} disconnected. Reason: ${reason || 'No reason'}`));

// Log in to Discord with your client's token
client.login(process.env.DISCORD_TOKEN)
    .then(() => logger.info('Successfully logged in to Discord.'))
    .catch(error => logger.error(`Failed to log in: ${error.message}`));

// Basic error handling
process.on('unhandledRejection', error => {
    logger.error('Unhandled promise rejection:', error);
});
process.on('uncaughtException', error => {
    logger.error('Uncaught exception:', error);
    // Optional: exit process on critical uncaught exceptions
    // process.exit(1);
});
