import { mqtt, iot } from 'aws-iot-device-sdk-v2';
console.log('Worker: Starting up');

let connection = null;
let currentConnectionId = 1;

self.onmessage = function(event) {
    const { type, params, topic, message, stamp } = event.data;
    console.log(`Worker: Received message of type: ${type}`);

    switch (type) {
        case 'connect':
            connect(params, stamp);
            break;
        case 'disconnect':
            disconnect(stamp);
            break;
        case 'is_connected':
            isConnected();
            break;
        case 'clear_topics':
            // No action needed in the worker
            break;
        case 'subscribe':
            subscribe(topic, stamp);
            break;
        case 'unsubscribe':
            unsubscribe(topic, stamp);
            break;
        case 'send':
            send(topic, message);
            break;
    }
};

function connect(params, stamp) {
    console.log('Worker: Attempting to connect');
    const { apiMqttUrl, apiMqttClientId, region, accessKeyId, secretAccessKey, sessionToken } = params;

    const configBuilder = iot.AwsIotMqttConnectionConfigBuilder.new_with_websockets();

    configBuilder.with_clean_session(true);
    configBuilder.with_client_id(apiMqttClientId);
    configBuilder.with_endpoint(apiMqttUrl);
    configBuilder.with_credentials(region, accessKeyId, secretAccessKey, sessionToken);
    configBuilder.with_keep_alive_seconds(30);
    configBuilder.with_ping_timeout_ms(3000);
    configBuilder.with_reconnect_max_sec(5);
    configBuilder.with_reconnect_min_sec(1);

    const config = configBuilder.build();
    const client = new mqtt.MqttClient();

    connection = client.new_connection(config);
    // increment connection id
    currentConnectionId++;

    setupConnectionListeners(currentConnectionId);

    connection.connect()
        .then(() => {
            console.log('Worker: Connection successful');
            self.postMessage({ type: 'connect_result', data: {success: true, connectionId: currentConnectionId, stamp} });
        })
        .catch((error) => {
            console.error('Worker: Connection failed', error);
            self.postMessage({ type: 'connect_result', data: {success: false, error: error.message, stamp} });
        });
}

function disconnect(stamp) {
    if (connection) {
        const connectionId = currentConnectionId;
        connection.disconnect()
            .then(() => {
                if(connectionId !== currentConnectionId) {
                    console.log('Worker: Connection Id mismatch, ignoring disconnect result', connectionId, currentConnectionId);
                    return;
                }
                self.postMessage({ type: 'disconnect_result', data: {success: true, stamp} });
            })
            .catch((error) => {
                if(connectionId !== currentConnectionId) {
                    console.log('Worker: Connection Id mismatch, ignoring disconnect result', connectionId, currentConnectionId);
                    return;
                }
                self.postMessage({ type: 'disconnect_result', data: { success: false, error: error.message, stamp} });
            });
        connection = null;
    } else {
        self.postMessage({ type: 'disconnect_result', data: {success: true, stamp} });
    }
}

function isConnected() {
    const connected = connection && connection.currentState === 0 && connection.desiredState === 0;
    self.postMessage({ type: 'is_connected_result', data:{connected} });
}

function subscribe(topic, stamp) {
    if (connection && connection.currentState === 0 && connection.desiredState === 0) {
        connection.subscribe(topic, mqtt.QoS.AtLeastOnce)
            .then(() => {
                self.postMessage({ type: 'subscribe_result', data: {success: true, stamp} });
            })
            .catch((error) => {
                self.postMessage({ type: 'subscribe_result', data: {success: false, error: error.message, stamp} });
            });
    } else {
        self.postMessage({ type: 'subscribe_result', data: {success: false, error: 'Not connected', stamp} });
    }
}

function unsubscribe(topic, stamp) {
    if (connection && connection.currentState === 0 && connection.desiredState === 0) {
        connection.unsubscribe(topic)
            .then(() => {
                self.postMessage({ type: 'unsubscribe_result', data: {success: true, stamp} });
            })
            .catch((error) => {
                self.postMessage({ type: 'unsubscribe_result', data: {success: false, error: error.message, stamp} });
            });
    } else {
        self.postMessage({ type: 'unsubscribe_result', data: {success: false, error: 'Not connected', stamp} });
    }
}

function send(topic, message) {
    if (connection && connection.currentState === 0 && connection.desiredState === 0) {
        connection.publish(topic, message, mqtt.QoS.AtLeastOnce, false);
    } else {
        console.error('Cannot send message: Not connected');
    }
}

function setupConnectionListeners(connectionId) {
    connection.on('connect', () => {
        if(connectionId !== currentConnectionId) {
            console.log('Worker: Connection Id mismatch, ignoring connect event', connectionId, currentConnectionId);
            return;
        }
        self.postMessage({ type: 'connect', connectionId: connectionId});
    });

    connection.on('disconnect', () => {
        if(connectionId !== currentConnectionId) {
            console.log('Worker: Connection Id mismatch, ignoring disconnect event', connectionId, currentConnectionId);
            return;
        }
        self.postMessage({ type: 'disconnect', connectionId: connectionId });
    });

    connection.on('error', (error) => {
        if(connectionId !== currentConnectionId) {
            console.log('Worker: Connection Id mismatch, ignoring error event', connectionId, currentConnectionId);
            return;
        }
        self.postMessage({ type: 'error', data: error });
    });

    connection.on('interrupt', (error) => {
        if(connectionId !== currentConnectionId) {
            console.log('Worker: Connection Id mismatch, ignoring interrupt event', connectionId, currentConnectionId);
            return;
        }
        self.postMessage({ type: 'interrupt', data: error, connectionId: connectionId });
    });

    connection.on('resume', (error) => {
        if(connectionId !== currentConnectionId) {
            console.log('Worker: Connection Id mismatch, ignoring resume event', connectionId, currentConnectionId);
            return;
        }
        self.postMessage({ type: 'resume', data: error, connectionId: connectionId });
    });

    connection.on('message', (topic, payload) => {
        if(connectionId !== currentConnectionId) {
            console.log('Worker: Connection Id mismatch, ignoring message event', connectionId, currentConnectionId);
            return;
        }
        self.postMessage({ type: 'message', data: { topic, payload }, connectionId: connectionId });
    });

    connection.on('connection_success', (error) => {
        if(connectionId !== currentConnectionId) {
            console.log('Worker: Connection Id mismatch, ignoring connection_success event', connectionId, currentConnectionId);
            return;
        }
        self.postMessage({ type: 'connection_success', data: error, connectionId: connectionId });
    });

    connection.on('connection_failure', (error) => {
        if(connectionId !== currentConnectionId) {
            console.log('Worker: Connection Id mismatch, ignoring connection_failure event', connectionId, currentConnectionId);
            return;
        }
        self.postMessage({ type: 'connection_failure', data: error, connectionId: connectionId });
    });
}

// Add this at the end of the file
console.log('Worker: Setup complete');
