const { Client, GatewayIntentBits } = require('discord.js');
const CommandHandler = require('./commands/CommandHandler');
const SubscriptionCommands = require('./commands/SubscriptionCommands');
const PlayerService = require('./services/PlayerService');
const SupabaseService = require('./services/SupabaseService');
const NotificationService = require('./services/NotificationService');
const Logger = require('./utils/Logger');
const ServerRegistrationService = require('./services/ServerRegistrationService');

class Bot {
    constructor(token, supabase, logger) {
        if (!logger || typeof logger.error !== 'function') {
            throw new Error('Invalid logger provided to Bot constructor');
        }

        this.client = new Client({ intents: [GatewayIntentBits.Guilds] });
        this.token = token;
        this.supabase = supabase;
        this.logger = logger;
        this.processingLock = new Map();
        
        // Initialize services
        this.playerService = new PlayerService(logger);
        this.serverRegistrationService = new ServerRegistrationService(supabase, logger);
        this.subscriptionCommands = new SubscriptionCommands(supabase, logger);
        this.notificationService = new NotificationService(this, supabase);
        
        // Initialize command handlers
        this.commandHandler = new CommandHandler(
            this.playerService, 
            this.supabase, 
            this.logger,
            this.serverRegistrationService,
            this.subscriptionCommands
        );

        // Setup event handlers
        this.client.on('ready', () => {
            this.logger.info(`Logged in as ${this.client.user.tag}`);
            // Start notification service after bot is ready
            this.notificationService.start().then(() => {
                this.logger.info('Notification service started successfully');
            }).catch(error => {
                this.logger.error('Failed to start notification service:', error);
            });
        });

        this.client.on('interactionCreate', this.handleInteraction.bind(this));
    }

    async start() {
        try {
            await this.client.login(this.token);
        } catch (error) {
            this.logger.error('Failed to start bot:', error);
            throw error;
        }
    }

    async handleInteraction(interaction) {
        if (!interaction.isCommand() && !interaction.isButton()) {
            this.logger.debug('Ignoring non-command/button interaction');
            return;
        }

        const lockKey = interaction.id;
        if (this.processingLock.get(lockKey)) {
            this.logger.debug('Interaction already being processed', { id: lockKey });
            return;
        }

        this.processingLock.set(lockKey, true);

        try {
            if (interaction.isCommand()) {
                // Remove ephemeral flag for finduser and matchhistory commands
                const isStatsCommand = ['finduser', 'matchhistory'].includes(interaction.commandName);
                await interaction.deferReply({ 
                    ephemeral: !isStatsCommand 
                });

                this.logger.debug('Processing command', {
                    command: interaction.commandName,
                    guild: interaction.guild?.name,
                    timestamp: new Date().toISOString()
                });

                await this.commandHandler.handleCommand(interaction);
            } else if (interaction.isButton()) {
                // For buttons, we'll still use deferUpdate to show the loading state
                await interaction.deferUpdate();
                await this.commandHandler.handleButton(interaction);
            }
        } catch (error) {
            this.logger.error('Command processing error:', {
                error: error.message,
                stack: error.stack,
                command: interaction.commandName,
                guild: interaction.guild?.name
            });

            try {
                if (!interaction.replied) {
                    await interaction.editReply({
                        content: '❌ An error occurred while processing your request.',
                        ephemeral: true
                    });
                }
            } catch (replyError) {
                this.logger.error('Failed to send error response:', replyError);
            }
        } finally {
            this.processingLock.delete(lockKey);
        }
    }
}

module.exports = Bot;