import { Hookified, HookifiedOptions } from "hookified";

//#region src/types.d.ts
/**
 * 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;
  /**
   * 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>;
};
//#endregion
//#region src/memory/message.d.ts
/**
 * 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>;
}
//#endregion
//#region src/memory/task.d.ts
/**
 * 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;
  };
}
//#endregion
//#region src/index.d.ts
/**
 * 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>;
}
//#endregion
export { type EnqueueTask, MemoryMessageProvider, MemoryTaskProvider, type Message, type MessageProvider, Qified, QifiedEvents, QifiedHooks, QifiedOptions, type Task, type TaskContext, type TaskHandler, type TaskProvider, type TaskProviderOptions, type TopicHandler };