{%- import "util.jinja.include" as util -%}
// This code was generated by the xRegistry tool.
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.

import { ServiceBusClient, ServiceBusReceiver, ServiceBusReceivedMessage } from '@azure/service-bus';

/**
 * A wrapper for the Azure Service Bus receiver that processes messages
 */
export class ServiceBusProcessor {
    private client: ServiceBusClient;
    private receiver: ServiceBusReceiver | null = null;
    private isProcessing: boolean = false;
    
    /**
     * Message handler for processing messages
     */
    public processMessage?: (message: ServiceBusReceivedMessage) => Promise<void>;
    
    /**
     * Error handler
     */
    public processError?: (error: Error) => Promise<void>;
    
    /**
     * Create a new ServiceBusProcessor
     * @param client The Azure Service Bus client
     */
    constructor(client: ServiceBusClient) {
        this.client = client;
    }
    
    /**
     * Start processing messages from a queue
     * @param queueName The queue name
     */
    async startQueue(queueName: string): Promise<void> {
        this.receiver = this.client.createReceiver(queueName);
        // Start processing in background (don't await)
        this.startProcessing().catch(err => {
            console.error('Processing loop error:', err);
            if (this.processError) {
                this.processError(err);
            }
        });
    }
    
    /**
     * Start processing messages from a topic subscription
     * @param topicName The topic name
     * @param subscriptionName The subscription name
     */
    async startSubscription(topicName: string, subscriptionName: string): Promise<void> {
        this.receiver = this.client.createReceiver(topicName, subscriptionName);
        // Start processing in background (don't await)
        this.startProcessing().catch(err => {
            console.error('Processing loop error:', err);
            if (this.processError) {
                this.processError(err);
            }
        });
    }
    
    /**
     * Start the message processing loop
     */
    private async startProcessing(): Promise<void> {
        if (!this.receiver) {
            throw new Error('Receiver not initialized');
        }
        
        this.isProcessing = true;
        
        while (this.isProcessing) {
            try {
                const messages = await this.receiver.receiveMessages(10, { maxWaitTimeInMs: 5000 });
                
                for (const message of messages) {
                    try {
                        if (this.processMessage) {
                            await this.processMessage(message);
                        }
                        
                        // Complete the message
                        await this.receiver.completeMessage(message);
                    } catch (error) {
                        console.error('Error processing message:', error);
                        
                        // Abandon the message so it can be redelivered
                        await this.receiver.abandonMessage(message);
                        
                        if (this.processError && error instanceof Error) {
                            await this.processError(error);
                        }
                    }
                }
            } catch (error) {
                console.error('Error receiving messages:', error);
                if (this.processError && error instanceof Error) {
                    await this.processError(error);
                }
            }
        }
    }
    
    /**
     * Stop processing messages
     */
    async stop(): Promise<void> {
        this.isProcessing = false;
        
        if (this.receiver) {
            await this.receiver.close();
            this.receiver = null;
        }
        
        // Note: Don't close the client here as it may be shared across multiple processors
        // The client should be closed by the caller when all processing is complete
    }
}
