const { Client, GatewayIntentBits, Events, EmbedBuilder, PermissionsBitField } = require('discord.js');
const { DisTube } = require('distube');
const { YtDlpPlugin } = require('@distube/yt-dlp');
const { SoundCloudPlugin } = require('@distube/soundcloud');
const { SpotifyPlugin } = require('@distube/spotify');
const { CronJob } = require('cron');
const path = require('path');
const fs = require('fs');

// Load environment variables
require('dotenv').config({ path: path.join(__dirname, '.env') });

// Setup FFMPEG
const ffmpegStatic = require('ffmpeg-static');
process.env.FFMPEG_PATH = ffmpegStatic;
const ffmpegDir = path.dirname(ffmpegStatic);
if (!process.env.PATH.includes(ffmpegDir)) {
    process.env.PATH = `${ffmpegDir}${path.delimiter}${process.env.PATH}`;
}

// Generate dependency report for debugging
try {
    const { generateDependencyReport } = require('@discordjs/voice');
    console.log("Dependency Report:\n" + generateDependencyReport());
} catch (e) {}

const client = new Client({
    intents: [
        GatewayIntentBits.Guilds,
        GatewayIntentBits.GuildVoiceStates,
        GatewayIntentBits.GuildMessages,
        GatewayIntentBits.MessageContent
    ]
});

// Detect libsodium
try {
    const sodium = require('libsodium-wrappers');
    sodium.ready.then(() => {
        logToFile("Encryption library (libsodium) is ready.");
    });
} catch (e) {
    logToFile("Warning: libsodium-wrappers not found or failed to load.");
}

const distube = new DisTube(client, {
    plugins: [
        new SoundCloudPlugin(),
        new SpotifyPlugin(),
        new YtDlpPlugin(),
    ],
    emitNewSongOnly: true,
    emitAddSongWhenCreatingQueue: false,
});

const VC_ID = process.env.VC_ID;
const AUDIO_PATH = path.join(__dirname, 'assets/audio/sahur.mp3');
const PREFIX = '!';

function logToFile(message) {
    const logMessage = `[${new Date().toISOString()}] ${message}\n`;
    try {
        fs.appendFileSync(path.join(__dirname, 'bot.log'), logMessage);
    } catch (err) {
        console.error('Failed to write to log file:', err);
    }
    console.log(message);
}

client.once(Events.ClientReady, () => {
    logToFile(`Bot berhasil login!`);
    logToFile(`Ready! Logged in as ${client.user.tag}`);
    logToFile(`FFMPEG Path: ${process.env.FFMPEG_PATH}`);

    // Sahur Alarm
    const rawSahurTime = process.env.SAHUR_TIME || '03:30'; 
    let cronTime = '30 3 * * *';
    
    if (rawSahurTime.includes(':')) {
        const [hour, minute] = rawSahurTime.split(':');
        cronTime = `${parseInt(minute)} ${parseInt(hour)} * * *`;
    } else {
        cronTime = rawSahurTime;
    }

    try {
        new CronJob(cronTime, async () => {
            logToFile('Sahur alarm triggered!');
            const guild = client.guilds.cache.first();
            if (!guild) return;
            const channel = guild.channels.cache.get(VC_ID);
            if (channel && fs.existsSync(AUDIO_PATH)) {
                distube.voices.join(channel).then(voice => {
                    const stream = fs.createReadStream(AUDIO_PATH);
                    voice.play(stream);
                }).catch(err => {
                    logToFile(`Alarm join error: ${err.message}`);
                });
            }
        }, null, true, 'Asia/Jakarta');
        logToFile(`Alarm scheduled at ${cronTime}`);
    } catch (e) {
        logToFile(`Failed to schedule alarm: ${e.message}`);
    }
});

// Slash Command Handler
client.on(Events.InteractionCreate, async interaction => {
    if (!interaction.isChatInputCommand()) return;

    const { commandName } = interaction;
    const voiceChannel = interaction.member?.voice.channel;

    try {
        if (commandName === 'join') {
            if (!voiceChannel) return interaction.reply({ content: 'Anda harus berada di voice channel!', ephemeral: true });
            await interaction.deferReply();
            await distube.voices.join(voiceChannel);
            await interaction.editReply('Sudah join! 🎧');
        }

        else if (commandName === 'testsahur') {
            if (!voiceChannel) return interaction.reply({ content: 'Anda harus berada di voice channel!', ephemeral: true });
            if (!fs.existsSync(AUDIO_PATH)) return interaction.reply({ content: `File audio tidak ditemukan di ${AUDIO_PATH}`, ephemeral: true });
            
            await interaction.deferReply();
            logToFile(`Playing local file using stream: ${AUDIO_PATH}`);
            try {
                const voice = await distube.voices.join(voiceChannel);
                const stream = fs.createReadStream(AUDIO_PATH);
                voice.play(stream);
                await interaction.editReply('Memainkan suara sahur... 📢');
            } catch (e) {
                logToFile(`Error in testsahur: ${e.message}`);
                await interaction.editReply(`Gagal memutar audio: ${e.message}`);
            }
        }

        else if (commandName === 'play') {
            const query = interaction.options.getString('query');
            if (!voiceChannel) return interaction.reply({ content: 'Anda harus berada di voice channel!', ephemeral: true });
            
            await interaction.deferReply();
            logToFile(`Fetching stream for: ${query}`);
            distube.play(voiceChannel, query, {
                member: interaction.member,
                textChannel: interaction.channel,
                interaction
            }).catch(e => {
                logToFile(`Play Error: ${e.message}`);
                interaction.editReply(`Terjadi kesalahan saat memutar: ${e.message}`);
            });
            await interaction.editReply(`Mencari: **${query}**... 🔍`);
        }

        else if (commandName === 'pause') {
            distube.pause(interaction.guildId);
            await interaction.reply('Musik dipause. ⏸️');
        }

        else if (commandName === 'resume') {
            distube.resume(interaction.guildId);
            await interaction.reply('Musik dilanjutkan. ▶️');
        }

        else if (commandName === 'skip') {
            await distube.skip(interaction.guildId);
            await interaction.reply('Lagu dilewati! ⏭️');
        }

        else if (commandName === 'stop') {
            await distube.stop(interaction.guildId);
            await interaction.reply('Musik dihentikan dan antrean dihapus. 👋');
        }
    } catch (error) {
        logToFile(`Interaction Error (${commandName}): ${error.message}`);
        if (!interaction.replied && !interaction.deferred) {
            await interaction.reply({ content: `Terjadi kesalahan: ${error.message}`, ephemeral: true });
        } else {
            await interaction.editReply({ content: `Terjadi kesalahan: ${error.message}`, ephemeral: true });
        }
    }
});

// Prefix Command Handler (Legacy/Backup)
client.on(Events.MessageCreate, async message => {
    if (message.author.bot || !message.content.startsWith(PREFIX)) return;

    const args = message.content.slice(PREFIX.length).trim().split(/ +/);
    const command = args.shift().toLowerCase();
    const voiceChannel = message.member?.voice.channel;

    try {
        if (command === 'play') {
            const query = args.join(' ');
            if (!voiceChannel) return message.reply('Anda harus berada di voice channel!');
            if (!query) return message.reply('Masukkan judul atau link lagu!');
            distube.play(voiceChannel, query, {
                member: message.member,
                textChannel: message.channel,
                message
            });
        } else if (['skip', 'stop', 'pause', 'resume'].includes(command)) {
            if (!voiceChannel) return message.reply('Anda harus berada di voice channel!');
            const method = command === 'skip' ? 'skip' : (command === 'stop' ? 'stop' : (command === 'pause' ? 'pause' : 'resume'));
            await distube[method](message.guildId);
            message.reply(`${command} berhasil!`);
        } else if (command === 'testsahur') {
            if (!voiceChannel) return message.reply('Anda harus berada di voice channel!');
            try {
                const voice = await distube.voices.join(voiceChannel);
                const stream = fs.createReadStream(AUDIO_PATH);
                voice.play(stream);
                message.reply('Mengetes suara sahur... 📢');
            } catch (e) {
                message.reply(`❌ Error: ${e.message}`);
            }
        }
    } catch (error) {
        logToFile(`Message Command Error: ${error.message}`);
        message.reply(`❌ Error: ${error.message}`);
    }
});

// DisTube Events
distube
    .on('playSong', (queue, song) => {
        queue.textChannel.send(`🎵 Sekarang memutar: **${song.name}** - \`${song.formatDuration}\`\nRequested by: ${song.user}`);
    })
    .on('addSong', (queue, song) => {
        queue.textChannel.send(`✅ **${song.name}** ditambahkan ke antrean oleh ${song.user}`);
    })
    .on('error', (channel, e) => {
        logToFile(`DisTube Error: ${e.message}`);
        if (e.message.includes('Sign in to confirm you’re not a bot')) {
            if (channel) channel.send(`❌ YouTube memblokir akses bot. Silakan coba link dari SoundCloud atau Spotify.`);
        } else if (channel) {
            channel.send(`❌ Terjadi kesalahan: ${e.message.slice(0, 2000)}`);
        }
    });

// Handle uncaught errors to prevent crash
process.on('unhandledRejection', error => {
    logToFile(`Unhandled Rejection: ${error.message}`);
    console.error(error);
});

process.on('uncaughtException', error => {
    logToFile(`Uncaught Exception: ${error.message}`);
    console.error(error);
});

// Login
client.login(process.env.DISCORD_TOKEN);
