import { HookifiedOptions, Hookified } from 'hookified';

/**
 * Message interface for the message provider
 * @template T - The type of the message data
 */
type Message<T = any> = {
    /**
     * Unique identifier for the message
     * @type {string}
     */
    id: string;
    /**
     * the provider that passed the message
     */
    providerId?: string;
    /**
     * The data of the message
     * @type {<T = any>}
     */
    data: T;
    /**
     * Timestamp of when the message was created
     * @type {number}
     */
    timestamp?: number;
    /**
     * Headers for additional metadata
     * @type {Record<string, string>}
     */
    headers?: Record<string, string>;
};
type TopicHandler = {
    id?: string;
    handler: (message: Message) => Promise<void>;
};
/**
 * MessageProvider interface for the message provider
 */
type MessageProvider = {
    /**
     * The id of the message provider. Use primary when multiple providers
     * are used.
     */
    id: string;
    /**
     * Array of handlers for message processing
     * @type {Map<string, Array<TopicHandler>>}
     */
    subscriptions: Map<string, TopicHandler[]>;
    /**
     * Plublish a message to a topic / queue. This is used to send messages to subscribers.
     * @param topic - The topic or queue to publish the message to
     * @param message - The message to be published
     * @returns {Promise<void>}
     */
    publish(topic: string, message: Omit<Message, "providerId">): Promise<void>;
    /**
     * Subscribe to a topic / queue. This is used to receive messages from the provider.
     * @param {TopicHandler} subscription - The topic or queue to subscribe to
     * @returns {Promise<void>}
     */
    subscribe(topic: string, handler: TopicHandler): Promise<void>;
    /**
     * Remove subscription to a topic / queue.
     * @param topic - The topic or queue to unsubscribe from
     * @param id - Optional unique identifier for the subscription to remove. If not provided, it will remove all subscriptions for the topic.
     * @returns {Promise<void>}
     */
    unsubscribe(topic: string, id?: string): Promise<void>;
    /**
     * Unsubscribe from a topic / queue. This is used to stop receiving messages from the provider.
     * @returns {Promise<void>}
     */
    disconnect(): Promise<void>;
};
/**
 * Task interface for the task provider
 * @template T - The type of the task data
 */
type Task<T = any> = {
    /**
     * Unique identifier for the task
     * @type {string}
     */
    id: string;
    /**
     * The data of the task
     * @type {<T = any>}
     */
    data: T;
    /**
     * Timestamp of when the task was created (milliseconds since epoch)
     * Set automatically by provider if not provided based on Date.now()
     * @type {number}
     */
    timestamp?: number;
    /**
     * Scheduled time for delayed task execution (milliseconds since epoch)
     * If set, task won't be processed until this time
     * @type {number}
     */
    scheduledAt?: number;
    /**
     * Headers for additional metadata
     * @type {Record<string, string>}
     */
    headers?: Record<string, string>;
    /**
     * Priority of the task (higher numbers = higher priority)
     * @type {number}
     * @default 0
     */
    priority?: number;
    /**
     * Maximum number of retry attempts
     * If undefined, uses provider default
     * @type {number}
     */
    maxRetries?: number;
    /**
     * Maximum processing time in milliseconds before task times out
     * If not set, uses provider default
     * @type {number}
     */
    timeout?: number;
};
/**
 * Task type for enqueueing tasks
 * Omits fields that are automatically generated by the provider
 * The provider will assign the id and timestamp when the task is enqueued
 */
type EnqueueTask = Omit<Task, "id" | "timestamp">;
/**
 * Context provided to task handlers for acknowledgment and task control
 * Allows handlers to acknowledge, reject, or extend processing time for tasks
 */
type TaskContext = {
    /**
     * Acknowledge successful task completion
     * Removes the task from the queue and marks it as completed
     * @returns {Promise<void>}
     */
    ack: () => Promise<void>;
    /**
     * Reject the task with explicit requeue control
     * @param requeue - If true, requeue for retry. If false, send to dead-letter queue. Defaults to true.
     * @returns {Promise<void>}
     */
    reject: (requeue?: boolean) => Promise<void>;
    /**
     * Extend the visibility timeout / processing deadline
     * Prevents task from being redelivered to another consumer while still processing
     * Useful for long-running tasks that need more time
     * @param ttl - Additional time to live in milliseconds
     * @returns {Promise<void>}
     */
    extend: (ttl: number) => Promise<void>;
    /**
     * Metadata about the current task execution
     * Provides context for retry logic and deadline management
     */
    metadata: {
        /**
         * Current retry attempt (0 = first attempt)
         * @type {number}
         */
        attempt: number;
        /**
         * Maximum retries allowed for this task
         * @type {number}
         */
        maxRetries: number;
    };
};
/**
 * Handler configuration for processing tasks from a queue
 * Defines how tasks should be processed and provides options for error handling
 */
type TaskHandler = {
    /**
     * Optional unique identifier for this handler
     * Used to identify and unsubscribe specific handlers
     * @type {string}
     */
    id?: string;
    /**
     * The handler function to process tasks
     * Called for each task dequeued from the queue
     * @param task - The task to process
     * @param context - Context for acknowledging, rejecting, or extending the task
     * @returns {Promise<void>}
     */
    handler: (task: Task, context: TaskContext) => Promise<void>;
};
/**
 * Configuration options for task providers
 * Allows customization of default behavior for task processing
 */
type TaskProviderOptions = {
    /**
     * Default timeout for task processing in milliseconds
     * Tasks exceeding this duration may be requeued or marked as failed
     * @type {number}
     */
    timeout?: number;
    /**
     * Default maximum number of retry attempts for failed tasks
     * After this many failures, tasks may be sent to dead-letter queue
     * @type {number}
     */
    retries?: number;
    /**
     * Name of the dead-letter queue for failed tasks
     * If not provided, dead-letter functionality is disabled
     * @type {string}
     */
    deadLetterQueue?: string;
};
/**
 * TaskProvider interface for task queue management
 * Handles enqueueing, dequeueing, and lifecycle management of tasks
 * Implementations should provide reliable task delivery and acknowledgment
 */
type TaskProvider = {
    /**
     * Unique identifier for this provider instance
     * Used to distinguish between multiple providers
     * @type {string}
     */
    id: string;
    /**
     * Default timeout for task processing in milliseconds
     * Can be overridden per task or per handler
     * @type {number}
     */
    timeout: number;
    /**
     * Default maximum number of retry attempts
     * Can be overridden per task
     * @type {number}
     */
    retries: number;
    /**
     * Name of the dead-letter queue for failed tasks
     * If not provided, dead-letter functionality is disabled
     * @type {string}
     */
    deadLetterQueue?: string;
    /**
     * Map of queue names to their registered handlers
     * Tracks all active handlers for each queue
     * @type {Map<string, TaskHandler[]>}
     */
    taskHandlers: Map<string, TaskHandler[]>;
    /**
     * Enqueue a task to a specific queue for processing
     * The task will be delivered to registered handlers for that queue
     * @param queue - The queue name to enqueue the task to
     * @param task - The task to be enqueued
     * @returns {Promise<string>} - the id of the task being queued
     */
    enqueue(queue: string, task: EnqueueTask): Promise<string>;
    /**
     * Register a handler to process tasks from a specific queue
     * The handler will be called for each task dequeued from the queue
     * @param queue - The queue name to dequeue tasks from
     * @param handler - The handler configuration for processing tasks
     * @returns {Promise<void>}
     */
    dequeue(queue: string, handler: TaskHandler): Promise<void>;
    /**
     * Unsubscribe a handler from a queue
     * Stops the handler from receiving new tasks
     * @param queue - The queue name to unsubscribe from
     * @param id - Optional handler ID. If not provided, removes all handlers for the queue
     * @returns {Promise<void>}
     */
    unsubscribe(queue: string, id?: string): Promise<void>;
    /**
     * Disconnect and clean up the provider
     * Stops receiving tasks, closes connections, and releases resources
     * Should be called before application shutdown
     * @returns {Promise<void>}
     */
    disconnect(): Promise<void>;
};

/**
 * Configuration options for the memory message provider.
 */
type MemoryMessageProviderOptions = {
    /**
     * The unique identifier for this provider instance.
     * @default "@qified/memory"
     */
    id?: string;
};
/**
 * In-memory message provider for testing and simple use cases.
 * Messages are stored and delivered synchronously in memory without persistence.
 */
declare class MemoryMessageProvider implements MessageProvider {
    private _subscriptions;
    private _id;
    /**
     * Creates an instance of MemoryMessageProvider.
     * @param {MemoryMessageProviderOptions} options - Optional configuration for the provider.
     */
    constructor(options?: MemoryMessageProviderOptions);
    /**
     * Gets the provider ID for the memory message provider.
     * @returns {string} The provider ID.
     */
    get id(): string;
    /**
     * Sets the provider ID for the memory message provider.
     * @param {string} id The new provider ID.
     */
    set id(id: string);
    /**
     * Gets the subscriptions map for all topics.
     * @returns {Map<string, TopicHandler[]>} The subscriptions map.
     */
    get subscriptions(): Map<string, TopicHandler[]>;
    /**
     * Sets the subscriptions map.
     * @param {Map<string, TopicHandler[]>} value The new subscriptions map.
     */
    set subscriptions(value: Map<string, TopicHandler[]>);
    /**
     * Publishes a message to a specified topic.
     * All handlers subscribed to the topic will be called synchronously in order.
     * @param {string} topic The topic to publish the message to.
     * @param {Message} message The message to publish.
     * @returns {Promise<void>} A promise that resolves when all handlers have been called.
     */
    publish(topic: string, message: Omit<Message, "providerId">): Promise<void>;
    /**
     * Subscribes to a specified topic.
     * @param {string} topic The topic to subscribe to.
     * @param {TopicHandler} handler The handler to process incoming messages.
     * @returns {Promise<void>} A promise that resolves when the subscription is complete.
     */
    subscribe(topic: string, handler: TopicHandler): Promise<void>;
    /**
     * Unsubscribes from a specified topic.
     * If an ID is provided, only the handler with that ID is removed.
     * If no ID is provided, all handlers for the topic are removed.
     * @param {string} topic The topic to unsubscribe from.
     * @param {string} [id] Optional identifier for the subscription to remove.
     * @returns {Promise<void>} A promise that resolves when the unsubscription is complete.
     */
    unsubscribe(topic: string, id?: string): Promise<void>;
    /**
     * Disconnects and clears all subscriptions.
     * @returns {Promise<void>} A promise that resolves when the disconnection is complete.
     */
    disconnect(): Promise<void>;
}

/**
 * Configuration options for the memory task provider.
 */
type MemoryTaskProviderOptions = TaskProviderOptions & {
    /**
     * The unique identifier for this provider instance.
     * @default "@qified/memory-task"
     */
    id?: string;
};
/**
 * In-memory task provider for testing and simple use cases.
 * Tasks are stored and processed in memory without persistence.
 * Supports task acknowledgment, rejection, retry, and timeout handling.
 */
declare class MemoryTaskProvider implements TaskProvider {
    private _id;
    private _timeout;
    private _retries;
    private _taskHandlers;
    private _queues;
    private _processing;
    private _deadLetterQueue;
    private _taskIdCounter;
    private _active;
    /**
     * Creates an instance of MemoryTaskProvider.
     * @param {MemoryTaskProviderOptions} options - Optional configuration for the provider.
     */
    constructor(options?: MemoryTaskProviderOptions);
    /**
     * Gets the provider ID for the memory task provider.
     * @returns {string} The provider ID.
     */
    get id(): string;
    /**
     * Sets the provider ID for the memory task provider.
     * @param {string} id The new provider ID.
     */
    set id(id: string);
    /**
     * Gets the default timeout for task processing.
     * @returns {number} The timeout in milliseconds.
     */
    get timeout(): number;
    /**
     * Sets the default timeout for task processing.
     * @param {number} timeout The timeout in milliseconds.
     */
    set timeout(timeout: number);
    /**
     * Gets the default maximum retry attempts.
     * @returns {number} The maximum retry attempts.
     */
    get retries(): number;
    /**
     * Sets the default maximum retry attempts.
     * @param {number} retries The maximum retry attempts.
     */
    set retries(retries: number);
    /**
     * Gets the task handlers map.
     * @returns {Map<string, TaskHandler[]>} The task handlers map.
     */
    get taskHandlers(): Map<string, TaskHandler[]>;
    /**
     * Sets the task handlers map.
     * @param {Map<string, TaskHandler[]>} value The new task handlers map.
     */
    set taskHandlers(value: Map<string, TaskHandler[]>);
    /**
     * Generates a unique task ID.
     * @returns {string} A unique task ID.
     */
    private generateTaskId;
    /**
     * Enqueues a task to a specific queue.
     * Automatically assigns ID and timestamp to the task.
     * @param {string} queue - The queue name to enqueue to.
     * @param {EnqueueTask} taskData - The task data to enqueue.
     * @returns {Promise<string>} The ID of the enqueued task.
     */
    enqueue(queue: string, taskData: EnqueueTask): Promise<string>;
    /**
     * Registers a handler to process tasks from a queue.
     * Starts processing any pending tasks in the queue.
     * @param {string} queue - The queue name to dequeue from.
     * @param {TaskHandler} handler - The handler configuration.
     * @returns {Promise<void>}
     */
    dequeue(queue: string, handler: TaskHandler): Promise<void>;
    /**
     * Processes tasks in a queue by delivering them to registered handlers.
     * @param {string} queue - The queue name to process.
     */
    private processQueue;
    /**
     * Processes a single task with a handler.
     * @param {string} queue - The queue name.
     * @param {QueuedTask} queuedTask - The queued task to process.
     * @param {TaskHandler} handler - The handler to process the task.
     */
    private processTask;
    /**
     * Removes a task from the queue.
     * @param {string} queue - The queue name.
     * @param {string} taskId - The task ID to remove.
     */
    private removeTask;
    /**
     * Moves a task to the dead-letter queue.
     * @param {string} queue - The original queue name.
     * @param {Task} task - The task to move.
     */
    private moveToDeadLetter;
    /**
     * Unsubscribes a handler from a queue.
     * @param {string} queue - The queue name to unsubscribe from.
     * @param {string} [id] - Optional handler ID. If not provided, removes all handlers.
     * @returns {Promise<void>}
     */
    unsubscribe(queue: string, id?: string): Promise<void>;
    /**
     * Disconnects and clears all queues and handlers.
     * Stops all task processing.
     * @returns {Promise<void>}
     */
    disconnect(): Promise<void>;
    /**
     * Gets all tasks in the dead-letter queue for a specific queue.
     * Useful for debugging and monitoring failed tasks.
     * @param {string} queue - The queue name.
     * @returns {Task[]} Array of tasks in the dead-letter queue.
     */
    getDeadLetterTasks(queue: string): Task[];
    /**
     * Gets the current state of a queue.
     * Useful for monitoring and debugging.
     * @param {string} queue - The queue name.
     * @returns {Object} Queue statistics.
     */
    getQueueStats(queue: string): {
        waiting: number;
        processing: number;
        deadLetter: number;
    };
}

/**
 * Standard events emitted by Qified.
 */
declare enum QifiedEvents {
    error = "error",
    info = "info",
    warn = "warn",
    publish = "publish",
    subscribe = "subscribe",
    unsubscribe = "unsubscribe",
    disconnect = "disconnect"
}
/**
 * Hook event names for before/after lifecycle hooks.
 * Before hooks receive a mutable context object that can be modified.
 * After hooks receive the final context after the operation completes.
 */
declare enum QifiedHooks {
    beforeSubscribe = "before:subscribe",
    afterSubscribe = "after:subscribe",
    beforePublish = "before:publish",
    afterPublish = "after:publish",
    beforeUnsubscribe = "before:unsubscribe",
    afterUnsubscribe = "after:unsubscribe",
    beforeDisconnect = "before:disconnect",
    afterDisconnect = "after:disconnect"
}
type QifiedOptions = {
    /**
     * The message providers to use.
     */
    messageProviders?: MessageProvider | MessageProvider[];
    /**
     * The task providers to use.
     */
    taskProviders?: TaskProvider | TaskProvider[];
} & HookifiedOptions;
declare class Qified extends Hookified {
    private _messageProviders;
    private _taskProviders;
    /**
     * Creates an instance of Qified.
     * @param {QifiedOptions} options - Optional configuration for Qified.
     */
    constructor(options?: QifiedOptions);
    /**
     * Gets or sets the message providers.
     * @returns {MessageProvider[]} The array of message providers.
     */
    get messageProviders(): MessageProvider[];
    /**
     * Sets the message providers.
     * @param {MessageProvider[]} providers - The array of message providers to set.
     */
    set messageProviders(providers: MessageProvider[]);
    /**
     * Gets or sets the task providers.
     * @returns {TaskProvider[]} The array of task providers.
     */
    get taskProviders(): TaskProvider[];
    /**
     * Sets the task providers.
     * @param {TaskProvider[]} providers - The array of task providers to set.
     */
    set taskProviders(providers: TaskProvider[]);
    /**
     * Subscribes to a topic. If you have multiple message providers, it will subscribe to the topic on all of them.
     * @param {string} topic - The topic to subscribe to.
     * @param {TopicHandler} handler - The handler to call when a message is published to the topic.
     */
    subscribe(topic: string, handler: TopicHandler): Promise<void>;
    /**
     * Publishes a message to a topic. If you have multiple message providers, it will publish the message to all of them.
     * @param {string} topic - The topic to publish to.
     * @param {Message} message - The message to publish.
     */
    publish(topic: string, message: Omit<Message, "providerId">): Promise<void>;
    /**
     * Unsubscribes from a topic. If you have multiple message providers, it will unsubscribe from the topic on all of them.
     * If an ID is provided, it will unsubscribe only that handler. If no ID is provided, it will unsubscribe all handlers for the topic.
     * @param topic - The topic to unsubscribe from.
     * @param id - The optional ID of the handler to unsubscribe. If not provided, all handlers for the topic will be unsubscribed.
     */
    unsubscribe(topic: string, id?: string): Promise<void>;
    /**
     * Disconnects from all providers.
     * This method will call the `disconnect` method on each message provider.
     */
    disconnect(): Promise<void>;
}

export { MemoryMessageProvider, MemoryTaskProvider, type Message, type MessageProvider, Qified, QifiedEvents, QifiedHooks, type QifiedOptions, type TaskProvider, type TopicHandler };
