const { createClient } = require('@supabase/supabase-js');
const Logger = require('../utils/Logger');

class SupabaseService {
    constructor() {
        this.logger = new Logger('SupabaseService');
        const supabaseUrl = process.env.SUPABASE_URL;
        const supabaseKey = process.env.SUPABASE_KEY;
      
        if (!supabaseUrl || !supabaseKey) {
            this.logger.error('Missing configuration', {
                hasUrl: !!supabaseUrl,
                hasKey: !!supabaseKey
            });
            this.supabase = null;
        } else {
            this.supabase = createClient(supabaseUrl, supabaseKey);
            this.logger.debug('Supabase client created');
        }
    }

    async testConnection() {
        if (!this.supabase) {
            this.logger.error('Client not initialized');
            return false;
        }

        try {
            this.logger.debug('Testing database connection...');
            
            // Test servers table
            const { data: serverTest, error: serverError } = await this.supabase
                .from('servers')
                .select('count')
                .limit(1);
                
            if (serverError) {
                this.logger.error('Server table test failed:', serverError);
                return false;
            }
            
            // Test games table
            const { data: gameTest, error: gameError } = await this.supabase
                .from('games')
                .select('count')
                .limit(1);
                
            if (gameError) {
                this.logger.error('Games table test failed:', gameError);
                return false;
            }

            this.logger.info('Database connection successful');
            return true;
        } catch (error) {
            this.logger.error('Connection test failed:', {
                error: error.message,
                stack: error.stack
            });
            return false;
        }
    }

    async ensureServerRegistered(guildId, serverName) {
        try {
            this.logger.debug('Ensuring server is registered', { guildId, serverName });
    
            // Try to find existing server
            const { data: existingServer, error: fetchError } = await this.supabase
                .from('servers')
                .select('*')
                .eq('discord_server_id', guildId)
                .single();
    
            // If server exists, return it
            if (existingServer) {
                this.logger.debug('Server already registered', { 
                    serverId: existingServer.id,
                    guildId, 
                    serverName: existingServer.server_name 
                });
                return existingServer;
            }
    
            // If server doesn't exist, create it
            this.logger.debug('Registering new server', { guildId, serverName });
            const { data: newServer, error: insertError } = await this.supabase
                .from('servers')
                .insert([{
                    discord_server_id: guildId,
                    server_name: serverName,
                    active: true
                }])
                .select()
                .single();
    
            if (insertError) {
                this.logger.error('Failed to register server', { 
                    error: insertError,
                    guildId,
                    serverName 
                });
                throw insertError;
            }
    
            this.logger.info('New server registered successfully', {
                serverId: newServer.id,
                guildId,
                serverName
            });
    
            return newServer;
        } catch (error) {
            this.logger.error('Error in ensureServerRegistered:', {
                error: error.message,
                stack: error.stack,
                guildId,
                serverName
            });
            throw error;
        }
    }
    
    // Update the addSubscription method to use ensureServerRegistered
    async addSubscription(guildId, gameName, channelId, serverName) {
        if (!this.supabase) {
            this.logger.error('Client not initialized');
            return null;
        }
    
        try {
            this.logger.debug('Adding subscription', { guildId, gameName, channelId });
    
            // Ensure server is registered
            const server = await this.ensureServerRegistered(guildId, serverName);
            if (!server) {
                throw new Error('Failed to ensure server registration');
            }
    
            // Get game ID
            const { data: gameData, error: gameError } = await this.supabase
                .from('games')
                .select('id')
                .eq('name', gameName)
                .eq('active', true)
                .single();
    
            if (gameError) {
                this.logger.error('Game fetch error:', { gameError, gameName });
                throw gameError;
            }
    
            // Create subscription
            const { data, error } = await this.supabase
                .from('server_game_preferences')
                .upsert({
                    server_id: server.id,
                    game_id: gameData.id,
                    notification_channel_id: channelId
                }, {
                    onConflict: '(server_id,game_id)',
                    returning: true
                });
    
            if (error) {
                this.logger.error('Subscription upsert error:', { error });
                throw error;
            }
    
            this.logger.debug('Subscription added successfully', {
                serverId: server.id,
                gameId: gameData.id,
                channelId
            });
    
            return data;
        } catch (error) {
            this.logger.error('Error in addSubscription:', {
                error: error.message,
                stack: error.stack,
                guildId,
                gameName
            });
            throw error;
        }
    }

    async getSubscriptions(guildId) {
        if (!this.supabase) {
            this.logger.error('Client not initialized');
            return [];
        }

        try {
            this.logger.debug('Fetching subscriptions', { guildId });
            
            const { data, error } = await this.supabase
                .from('server_game_preferences')
                .select(`
                    games (name),
                    notification_channel_id,
                    servers!inner (discord_server_id)
                `)
                .eq('servers.discord_server_id', guildId);

            if (error) {
                this.logger.error('Error fetching subscriptions:', { error, guildId });
                throw error;
            }

            this.logger.debug('Subscriptions fetched', { 
                count: data?.length || 0,
                guildId 
            });
            
            return data || [];
        } catch (error) {
            this.logger.error('Error in getSubscriptions:', {
                error: error.message,
                stack: error.stack,
                guildId
            });
            throw error;
        }
    }

    async addSubscription(guildId, gameName, channelId) {
        if (!this.supabase) {
            this.logger.error('Client not initialized');
            return null;
        }

        try {
            this.logger.debug('Adding subscription', { guildId, gameName, channelId });

            // First, get or create server record
            const { data: serverData, error: serverError } = await this.supabase
                .from('servers')
                .upsert({
                    discord_server_id: guildId,
                    active: true
                }, {
                    onConflict: 'discord_server_id',
                    returning: true
                });

            if (serverError) {
                this.logger.error('Server upsert error:', { serverError, guildId });
                throw serverError;
            }

            if (!serverData || serverData.length === 0) {
                this.logger.error('Server creation failed - no data returned', { guildId });
                throw new Error('Server creation failed');
            }

            // Get game ID
            const { data: gameData, error: gameError } = await this.supabase
                .from('games')
                .select('id')
                .eq('name', gameName)
                .eq('active', true)
                .single();

            if (gameError) {
                this.logger.error('Game fetch error:', { gameError, gameName });
                throw gameError;
            }

            // Create subscription
            const { data, error } = await this.supabase
                .from('server_game_preferences')
                .upsert({
                    server_id: serverData[0].id,
                    game_id: gameData.id,
                    notification_channel_id: channelId
                }, {
                    onConflict: '(server_id,game_id)',
                    returning: true
                });

            if (error) {
                this.logger.error('Subscription upsert error:', { error });
                throw error;
            }

            this.logger.debug('Subscription added successfully', {
                serverId: serverData[0].id,
                gameId: gameData.id,
                channelId
            });

            return data;
        } catch (error) {
            this.logger.error('Error in addSubscription:', {
                error: error.message,
                stack: error.stack,
                guildId,
                gameName
            });
            throw error;
        }
    }

    async removeSubscription(guildId, gameName) {
        if (!this.supabase) {
            this.logger.error('Client not initialized');
            return null;
        }

        try {
            this.logger.debug('Removing subscription', { guildId, gameName });

            // Get server ID
            const { data: serverData, error: serverError } = await this.supabase
                .from('servers')
                .select('id')
                .eq('discord_server_id', guildId)
                .single();

            if (serverError) {
                this.logger.error('Server fetch error:', { serverError, guildId });
                throw serverError;
            }

            // Get game ID
            const { data: gameData, error: gameError } = await this.supabase
                .from('games')
                .select('id')
                .eq('name', gameName)
                .single();

            if (gameError) {
                this.logger.error('Game fetch error:', { gameError, gameName });
                throw gameError;
            }

            // Delete subscription
            const { data, error } = await this.supabase
                .from('server_game_preferences')
                .delete()
                .match({
                    server_id: serverData.id,
                    game_id: gameData.id
                })
                .single();

            if (error) {
                this.logger.error('Subscription deletion error:', { error });
                throw error;
            }

            this.logger.debug('Subscription removed successfully', {
                serverId: serverData.id,
                gameId: gameData.id
            });

            return data;
        } catch (error) {
            this.logger.error('Error in removeSubscription:', {
                error: error.message,
                stack: error.stack,
                guildId,
                gameName
            });
            throw error;
        }
    }

    getClient() {
        return this.supabase;
    }
}

module.exports = SupabaseService;