const axios = require('axios');
const logger = require('../utils/logger');

class ListmonkService {
    constructor() {
        this.baseURL = process.env.LISTMONK_API_URL || 'http://listmonk:9000/api';
        this.username = process.env.LISTMONK_USERNAME;
        this.password = process.env.LISTMONK_PASSWORD;
        this.lists = {
            locations: null,
            users: null,
            supportLevel1: null,
            supportLevel2: null,
            supportLevel3: null,
            supportLevel4: null,
            hasSign: null,
            wantsSign: null,
            signRegular: null,
            signLarge: null,
            signUnsure: null
        };
        
        // Debug logging for environment variables
        console.log('🔍 Listmonk Environment Variables:');
        console.log(`  LISTMONK_SYNC_ENABLED: ${process.env.LISTMONK_SYNC_ENABLED}`);
        console.log(`  LISTMONK_API_URL: ${process.env.LISTMONK_API_URL}`);
        console.log(`  LISTMONK_USERNAME: ${this.username ? 'SET' : 'NOT SET'}`);
        console.log(`  LISTMONK_PASSWORD: ${this.password ? 'SET' : 'NOT SET'}`);
        
        this.syncEnabled = process.env.LISTMONK_SYNC_ENABLED === 'true';
        
        // Additional validation - disable if credentials are missing
        if (this.syncEnabled && (!this.username || !this.password)) {
            logger.warn('Listmonk credentials missing - disabling sync');
            this.syncEnabled = false;
        }
        
        console.log(`  Final syncEnabled: ${this.syncEnabled}`);
        
        this.lastError = null;
        this.lastErrorTime = null;
    }

    // Create axios instance with auth
    getClient() {
        return axios.create({
            baseURL: this.baseURL,
            auth: {
                username: this.username,
                password: this.password
            },
            headers: {
                'Content-Type': 'application/json'
            },
            timeout: 10000 // 10 second timeout
        });
    }

    // Test connection to Listmonk
    async checkConnection() {
        if (!this.syncEnabled) {
            return false;
        }

        try {
            console.log(`🔍 Testing connection to: ${this.baseURL}`);
            console.log(`🔍 Using credentials: ${this.username}:${this.password ? 'SET' : 'NOT SET'}`);
            
            const client = this.getClient();
            console.log('🔍 Making request to /health endpoint...');
            const { data } = await client.get('/health');
            
            console.log('🔍 Response received:', JSON.stringify(data, null, 2));
            
            if (data.data === true) {
                logger.info('Listmonk connection successful');
                this.lastError = null;
                this.lastErrorTime = null;
                return true;
            }
            console.log('🔍 Health check failed - data.data is not true');
            return false;
        } catch (error) {
            console.log('🔍 Connection error details:', error.message);
            if (error.response) {
                console.log('🔍 Response status:', error.response.status);
                console.log('🔍 Response data:', error.response.data);
            }
            this.lastError = `Listmonk connection failed: ${error.message}`;
            this.lastErrorTime = new Date();
            logger.error(this.lastError);
            return false;
        }
    }

    // Initialize all lists on startup
    async initializeLists() {
        if (!this.syncEnabled) {
            logger.info('Listmonk sync is disabled');
            return false;
        }

        try {
            // Check connection first
            const connected = await this.checkConnection();
            if (!connected) {
                // Use the actual error message from checkConnection
                throw new Error(`Cannot connect to Listmonk: ${this.lastError || 'Unknown connection error'}`);
            }

            // Create or get main lists
            this.lists.locations = await this.ensureList({
                name: 'Map Locations - All',
                type: 'private',
                optin: 'single',
                tags: ['map', 'locations', 'automated'],
                description: 'All locations from the map application'
            });

            this.lists.users = await this.ensureList({
                name: 'Map Users - All',
                type: 'private',
                optin: 'single',
                tags: ['map', 'users', 'automated'],
                description: 'All registered users from the map application'
            });

            // Create support level lists
            this.lists.supportLevel1 = await this.ensureList({
                name: 'Support Level 1',
                type: 'private',
                optin: 'single',
                tags: ['map', 'support-level-1', 'automated'],
                description: 'Strong supporters (Level 1 - Green)'
            });

            this.lists.supportLevel2 = await this.ensureList({
                name: 'Support Level 2',
                type: 'private',
                optin: 'single',
                tags: ['map', 'support-level-2', 'automated'],
                description: 'Moderate supporters (Level 2 - Yellow)'
            });

            this.lists.supportLevel3 = await this.ensureList({
                name: 'Support Level 3',
                type: 'private',
                optin: 'single',
                tags: ['map', 'support-level-3', 'automated'],
                description: 'Weak supporters (Level 3 - Orange)'
            });

            this.lists.supportLevel4 = await this.ensureList({
                name: 'Support Level 4',
                type: 'private',
                optin: 'single',
                tags: ['map', 'support-level-4', 'automated'],
                description: 'Opponents (Level 4 - Red)'
            });

            // Create sign status lists
            this.lists.hasSign = await this.ensureList({
                name: 'Has Campaign Sign',
                type: 'private',
                optin: 'single',
                tags: ['map', 'has-sign', 'automated'],
                description: 'Locations with campaign signs'
            });

            this.lists.wantsSign = await this.ensureList({
                name: 'Sign Requests',
                type: 'private',
                optin: 'single',
                tags: ['map', 'sign-requests', 'automated'],
                description: 'Supporters without signs (potential sign placements)'
            });

            // Create sign size lists
            this.lists.signRegular = await this.ensureList({
                name: 'Regular Signs',
                type: 'private',
                optin: 'single',
                tags: ['map', 'sign-regular', 'automated'],
                description: 'Locations with regular-sized campaign signs'
            });

            this.lists.signLarge = await this.ensureList({
                name: 'Large Signs',
                type: 'private',
                optin: 'single',
                tags: ['map', 'sign-large', 'automated'],
                description: 'Locations with large-sized campaign signs'
            });

            this.lists.signUnsure = await this.ensureList({
                name: 'Sign Size Unsure',
                type: 'private',
                optin: 'single',
                tags: ['map', 'sign-unsure', 'automated'],
                description: 'Locations with unsure sign size preferences'
            });

            logger.info('✅ Listmonk lists initialized successfully');
            return true;

        } catch (error) {
            this.lastError = `Failed to initialize Listmonk lists: ${error.message}`;
            this.lastErrorTime = new Date();
            logger.error(this.lastError);
            return false;
        }
    }

    // Ensure a list exists, create if not
    async ensureList(listConfig) {
        try {
            const client = this.getClient();
            
            // First, try to find existing list by name
            const { data: listsResponse } = await client.get('/lists');
            const existingList = listsResponse.data.results.find(list => list.name === listConfig.name);
            
            if (existingList) {
                logger.info(`📋 Found existing list: ${listConfig.name}`);
                return existingList;
            }

            // Create new list
            const { data: createResponse } = await client.post('/lists', listConfig);
            logger.info(`📋 Created new list: ${listConfig.name}`);
            return createResponse.data;

        } catch (error) {
            logger.error(`Failed to ensure list ${listConfig.name}:`, error.message);
            throw error;
        }
    }

    // Sync a location to Listmonk
    async syncLocation(locationData) {
        console.log('🔍 syncLocation called with:', {
            hasEmail: !!locationData.Email,
            email: locationData.Email,
            syncEnabled: this.syncEnabled,
            firstName: locationData['First Name'],
            lastName: locationData['Last Name'],
            supportLevel: locationData['Support Level'],
            sign: locationData.Sign,
            signType: typeof locationData.Sign,
            signValue: String(locationData.Sign),
            signRequested: locationData['Sign Requested'],
            wantsSign: locationData['Wants Sign']
        });

        // Let's also see all keys in the locationData to see if the field name is different
        console.log('🔍 All locationData keys:', Object.keys(locationData));
        console.log('🔍 Sign-related fields check:', {
            'Sign': locationData.Sign,
            'Sign Size': locationData['Sign Size'],
            'sign': locationData.sign,
            'Campaign Sign': locationData['Campaign Sign'],
            'Sign Type': locationData['Sign Type'],
            'Has Sign': locationData['Has Sign'],
            'Yard Sign': locationData['Yard Sign']
        });

        if (!this.syncEnabled || !locationData.Email) {
            console.log('🔍 Sync disabled or no email - returning failure');
            return { success: false, error: 'Sync disabled or no email provided' };
        }

        try {
            // Check if they have a sign - based on Sign Size field having a value
            const signSize = locationData['Sign Size'];
            const hasSignValue = signSize && signSize !== '' && signSize !== null && signSize !== 'null';
            
            console.log('🔍 Sign detection:', {
                'Sign Size': signSize,
                'Sign Size Type': typeof signSize,
                'Has Sign Value': hasSignValue,
                'Sign Boolean': locationData.Sign
            });

            const subscriberData = {
                email: locationData.Email,
                name: `${locationData['First Name'] || ''} ${locationData['Last Name'] || ''}`.trim(),
                status: 'enabled',
                lists: [this.lists.locations.id],
                attribs: {
                    address: locationData.Address,
                    support_level: locationData['Support Level'],
                    has_sign: locationData.Sign === true,
                    sign_type: signSize || null,
                    sign_boolean: locationData.Sign,
                    unit_number: locationData['Unit Number'],
                    phone: locationData.Phone,
                    notes: locationData.Notes
                }
            };

            // Add to support level lists
            const supportLevel = locationData['Support Level'];
            if (supportLevel && this.lists[`supportLevel${supportLevel}`]) {
                subscriberData.lists.push(this.lists[`supportLevel${supportLevel}`].id);
            }

            // Add to sign status lists
            // 1. Has Campaign Sign = only if Sign boolean is true (they physically have a sign)
            if (locationData.Sign === true) {
                subscriberData.lists.push(this.lists.hasSign.id);
                console.log('🔍 Added to hasSign list because Sign boolean is true');
            }
            
            // 2. Sign Requests = if they selected a sign size but Sign boolean is false (want sign, don't have it yet)
            if (hasSignValue && locationData.Sign !== true) {
                subscriberData.lists.push(this.lists.wantsSign.id);
                console.log('🔍 Added to wantsSign list because they selected sign size but Sign boolean is false');
            }
            
            // 3. Add to specific sign size lists based on Sign Size selection
            if (hasSignValue) {
                const signSizeLower = signSize.toLowerCase();
                if (signSizeLower === 'regular' && this.lists.signRegular) {
                    subscriberData.lists.push(this.lists.signRegular.id);
                    console.log('🔍 Added to signRegular list');
                } else if (signSizeLower === 'large' && this.lists.signLarge) {
                    subscriberData.lists.push(this.lists.signLarge.id);
                    console.log('🔍 Added to signLarge list');
                } else if (signSizeLower === 'unsure' && this.lists.signUnsure) {
                    subscriberData.lists.push(this.lists.signUnsure.id);
                    console.log('🔍 Added to signUnsure list');
                }
            }

            const client = this.getClient();
            
            // Check if subscriber already exists
            try {
                const { data: existingResponse } = await client.get(`/subscribers?query=${encodeURIComponent(`email = '${locationData.Email}'`)}`);
                if (existingResponse.data.results && existingResponse.data.results.length > 0) {
                    // Update existing subscriber
                    const subscriberId = existingResponse.data.results[0].id;
                    await client.put(`/subscribers/${subscriberId}`, subscriberData);
                    logger.debug(`📍 Updated location subscriber: ${locationData.Email}`);
                } else {
                    // Create new subscriber
                    await client.post('/subscribers', subscriberData);
                    logger.debug(`📍 Created location subscriber: ${locationData.Email}`);
                }
                console.log('🔍 Location sync successful - returning success');
                return { success: true };
            } catch (subscriptionError) {
                console.log('🔍 Subscriber search failed, trying to create new:', subscriptionError.message);
                // If subscriber doesn't exist, create new one
                await client.post('/subscribers', subscriberData);
                logger.debug(`📍 Created location subscriber: ${locationData.Email}`);
                console.log('🔍 Location sync successful (fallback) - returning success');
                return { success: true };
            }

        } catch (error) {
            console.log('🔍 Location sync failed with error:', error.message);
            logger.error(`Failed to sync location ${locationData.Email}:`, error.message);
            return { success: false, error: error.message };
        }
    }

    // Sync a user to Listmonk
    async syncUser(userData) {
        if (!this.syncEnabled || !userData.Email) {
            return { success: false, error: 'Sync disabled or no email provided' };
        }

        try {
            const subscriberData = {
                email: userData.Email,
                name: userData.Name || userData.Email,
                status: 'enabled',
                lists: [this.lists.users.id],
                attribs: {
                    user_type: userData.UserType || 'user',
                    admin: userData.Admin || false,
                    created_at: userData['Created At'] || userData.created_at,
                    last_login: userData['Last Login'] || userData.last_login
                }
            };

            const client = this.getClient();
            
            // Check if subscriber already exists
            try {
                const { data: existingResponse } = await client.get(`/subscribers?query=${encodeURIComponent(`email = '${userData.Email}'`)}`);
                if (existingResponse.data.results && existingResponse.data.results.length > 0) {
                    // Update existing subscriber
                    const subscriberId = existingResponse.data.results[0].id;
                    await client.put(`/subscribers/${subscriberId}`, subscriberData);
                    logger.debug(`👤 Updated user subscriber: ${userData.Email}`);
                } else {
                    // Create new subscriber
                    await client.post('/subscribers', subscriberData);
                    logger.debug(`👤 Created user subscriber: ${userData.Email}`);
                }
                return { success: true };
            } catch (subscriptionError) {
                // If subscriber doesn't exist, create new one
                await client.post('/subscribers', subscriberData);
                logger.debug(`👤 Created user subscriber: ${userData.Email}`);
                return { success: true };
            }

        } catch (error) {
            logger.error(`Failed to sync user ${userData.Email}:`, error.message);
            return { success: false, error: error.message };
        }
    }

    // Remove subscriber from Listmonk
    async removeSubscriber(email) {
        if (!this.syncEnabled || !email) {
            return { success: false, error: 'Sync disabled or no email provided' };
        }

        try {
            const client = this.getClient();
            const { data: response } = await client.get(`/subscribers?query=${encodeURIComponent(`email = '${email}'`)}`);
            
            if (response.data.results && response.data.results.length > 0) {
                const subscriberId = response.data.results[0].id;
                await client.delete(`/subscribers/${subscriberId}`);
                logger.debug(`🗑️ Removed subscriber: ${email}`);
                return { success: true };
            }
            
            return { success: false, error: 'Subscriber not found' };
        } catch (error) {
            logger.error(`Failed to remove subscriber ${email}:`, error.message);
            return { success: false, error: error.message };
        }
    }

    // Bulk sync multiple records
    async bulkSync(records, type) {
        if (!this.syncEnabled || !records || records.length === 0) {
            return { success: 0, failed: 0 };
        }

        let successCount = 0;
        let failedCount = 0;

        for (const record of records) {
            try {
                let result;
                if (type === 'location') {
                    result = await this.syncLocation(record);
                } else if (type === 'user') {
                    result = await this.syncUser(record);
                }

                if (result && result.success) {
                    successCount++;
                } else {
                    failedCount++;
                }
            } catch (error) {
                failedCount++;
                logger.error(`Bulk sync failed for record:`, error.message);
            }
        }

        logger.info(`📊 Bulk sync completed: ${successCount} success, ${failedCount} failed`);
        return { success: successCount, failed: failedCount };
    }

    // Get sync status
    getSyncStatus() {
        return {
            enabled: this.syncEnabled,
            connected: this.lastError === null,
            lastError: this.lastError,
            lastErrorTime: this.lastErrorTime,
            listsInitialized: Object.values(this.lists).some(list => list !== null)
        };
    }

    // Get list statistics
    async getListStats() {
        if (!this.syncEnabled) return null;

        try {
            const client = this.getClient();
            const { data } = await client.get('/lists');
            
            const stats = {};
            for (const [key, list] of Object.entries(this.lists)) {
                if (list) {
                    const listData = data.data.results.find(l => l.id === list.id);
                    stats[key] = {
                        name: list.name,
                        subscriber_count: listData ? listData.subscriber_count : 0
                    };
                }
            }
            
            return stats;
        } catch (error) {
            logger.error('Failed to get list stats:', error.message);
            return null;
        }
    }
}

// Export singleton instance
module.exports = new ListmonkService();
