import { z } from 'zod';

/**
 * @file src/brokers/adapter.types.ts
 * @description Defines the "Universal Broker Contract" for any messaging client
 * that wants to be instrumented by SyntropyLog. These generic interfaces
 * are key to decoupling the framework from specific implementations like
 * RabbitMQ or Kafka.
 */
/**
 * @interface BrokerMessage
 * @description Represents a standard message format that the framework understands.
 * The adapter is responsible for converting the broker-specific message
 * format to this structure, and vice-versa.
 */
interface BrokerMessage {
    /**
     * The actual content of the message. Using `Buffer` is the most flexible
     * approach as it supports any type of serialization (JSON, Avro, Protobuf, etc.).
     */
    payload: Buffer;
    /**
     * Key-value metadata attached to the message.
     * This is where SyntropyLog will inject tracing headers like `correlation-id`.
     */
    headers?: Record<string, string | Buffer>;
}
/**
 * @interface MessageLifecycleControls
 * @description Defines the controls for handling a received message's lifecycle.
 * An instance of this is passed to the user's message handler, allowing them
 * to confirm or reject the message.
 */
interface MessageLifecycleControls {
    /**
     * Acknowledges that the message has been successfully processed.
     * This typically removes the message from the queue.
     * @returns {Promise<void>}
     */
    ack: () => Promise<void>;
    /**
     * Negatively acknowledges the message, indicating a processing failure.
     * @param {boolean} [requeue=false] - If true, asks the broker to re-queue the message
     * for another attempt. If false (or omitted), the broker might move it to a dead-letter queue
     * or discard it, depending on its configuration.
     * @returns {Promise<void>}
     */
    nack: (requeue?: boolean) => Promise<void>;
}
/**
 * @type MessageHandler
 * @description The signature for the user-provided function that will process incoming messages.
 * @param {BrokerMessage} message - The received message in the framework's standard format.
 * @param {MessageLifecycleControls} controls - The functions to manage the message's lifecycle (ack/nack).
 * @returns {Promise<void>}
 */
type MessageHandler = (message: BrokerMessage, controls: MessageLifecycleControls) => Promise<void>;
/**
 * @interface IBrokerAdapter
 * @description The interface that every Broker Client Adapter must implement.
 * This is the "plug" where users will connect their specific messaging clients
 * (e.g., `amqplib`, `kafkajs`).
 */
interface IBrokerAdapter {
    /**
     * Establishes a connection to the message broker.
     * @returns {Promise<void>}
     */
    connect(): Promise<void>;
    /**
     * Gracefully disconnects from the broker.
     */
    /**
     * Gracefully disconnects from the message broker.
     * @returns {Promise<void>}
     */
    disconnect(): Promise<void>;
    /**
     * Publishes a message to a specific topic or routing key.
     * @param {string} topic - The destination for the message (e.g., a topic name, queue name, or routing key).
     * @param {BrokerMessage} message - The message to be sent, in the framework's standard format.
     * @returns {Promise<void>}
     */
    publish(topic: string, message: BrokerMessage): Promise<void>;
    /**
     * Subscribes to a topic or queue to receive messages.
     * @param {string} topic - The source of messages to listen to (e.g., a topic name or queue name).
     * @param {MessageHandler} handler - The user's function that will be called for each incoming message.
     * @returns {Promise<void>}
     */
    subscribe(topic: string, handler: MessageHandler): Promise<void>;
}

/**
 * @file src/logger/levels.ts
 * @description Defines the available log levels, their names, and their severity weights.
 */
/**
 * @description A mapping of log level names to their severity weights.
 * Higher numbers indicate higher severity.
 */
declare const LOG_LEVEL_WEIGHTS: {
    readonly fatal: 60;
    readonly error: 50;
    readonly warn: 40;
    readonly info: 30;
    readonly debug: 20;
    readonly trace: 10;
    readonly silent: 0;
};
/**
 * @description The type representing a valid log level name.
 */
type LogLevel = keyof typeof LOG_LEVEL_WEIGHTS;

/**
 * Internal Types for SyntropyLog Framework
 *
 * These types and utilities are for advanced usage and internal framework operations.
 * Use with caution - they may change between versions.
 */
/**
 * Represents any value that can be safely serialized to JSON.
 * This is a recursive type used to ensure type safety for log metadata.
 */
type JsonValue = string | number | boolean | null | {
    [key: string]: JsonValue;
} | JsonValue[];
/**
 * Type for log metadata objects that can be passed to logging methods
 */
type LogMetadata = Record<string, JsonValue>;
/**
 * Type for log bindings that are attached to logger instances
 */
type LogBindings = Record<string, JsonValue>;
/**
 * Type for retention rules that can be attached to loggers
 */
type LogRetentionRules = {
    ttl?: number;
    maxSize?: number;
    maxEntries?: number;
    archiveAfter?: number;
    deleteAfter?: number;
    [key: string]: JsonValue | number | undefined;
};
/**
 * Type for format arguments that can be passed to logging methods
 */
type LogFormatArg = string | number | boolean | null | undefined;
/**
 * Type for values that can be stored in context
 */
type ContextValue = string | number | boolean | null | undefined | Buffer | JsonValue;
/**
 * Type for context data structure
 */
type ContextData = Record<string, ContextValue>;
/**
 * Type for context configuration options
 */
type ContextConfig = {
    correlationIdHeader?: string;
    transactionIdHeader?: string;
    [key: string]: ContextValue;
};
/**
 * Type for context headers used in HTTP requests
 */
type ContextHeaders = Record<string, string>;
/**
 * Type for context callback functions
 */
type ContextCallback = () => void | Promise<void>;
/**
 * Type for logging matrix configuration
 */
type LoggingMatrix = Partial<Record<string, string[]>>;
/**
 * Type for filtered context based on log level
 */
type FilteredContext = Record<string, unknown>;

/**
 * Defines the public interface for a logger instance.
 * This ensures a consistent API for logging across the application,
 * including standard logging methods and a fluent API for contextual logging.
 */
interface ILogger {
    level: LogLevel;
    /**
     * Logs a message at the 'fatal' level. The application will likely exit.
     * @param {...(LogFormatArg | LogMetadata | JsonValue)[]} args - The arguments to log (metadata object, message, or format args).
     */
    fatal(...args: (LogFormatArg | LogMetadata | JsonValue)[]): Promise<void>;
    /**
     * Logs a message at the 'error' level.
     * @param {...(LogFormatArg | LogMetadata | JsonValue)[]} args - The arguments to log (metadata object, message, or format args).
     */
    error(...args: (LogFormatArg | LogMetadata | JsonValue)[]): Promise<void>;
    /**
     * Logs a message at the 'warn' level.
     * @param {...(LogFormatArg | LogMetadata | JsonValue)[]} args - The arguments to log (metadata object, message, or format args).
     */
    warn(...args: (LogFormatArg | LogMetadata | JsonValue)[]): Promise<void>;
    /**
     * Logs a message at the 'info' level.
     * @param {...(LogFormatArg | LogMetadata | JsonValue)[]} args - The arguments to log (metadata object, message, or format args).
     */
    info(...args: (LogFormatArg | LogMetadata | JsonValue)[]): Promise<void>;
    /**
     * Logs a message at the 'debug' level.
     * @param {...(LogFormatArg | LogMetadata | JsonValue)[]} args - The arguments to log (metadata object, message, or format args).
     */
    debug(...args: (LogFormatArg | LogMetadata | JsonValue)[]): Promise<void>;
    /**
     * Logs a message at the 'trace' level.
     * @param {...(LogFormatArg | LogMetadata | JsonValue)[]} args - The arguments to log (metadata object, message, or format args).
     */
    trace(...args: (LogFormatArg | LogMetadata | JsonValue)[]): Promise<void>;
    /**
     * Creates a new child logger instance with bindings that will be present in every log.
     * The child inherits all settings from the parent, adding or overriding the specified bindings.
     * @param {LogBindings} bindings - Key-value pairs to bind to the child logger.
     * @returns {ILogger} A new `ILogger` instance.
     */
    child(bindings: LogBindings): ILogger;
    /**
     * Dynamically updates the minimum log level for this logger instance.
     * Any messages with a severity lower than the new level will be ignored.
     * @param {LogLevel} level - The new log level to set.
     */
    setLevel(level: LogLevel): void;
    /**
     * Creates a new logger instance with a `source` field bound to it.
     * This is useful for creating a logger for a specific module or component.
     * @param {string} source - The name of the source (e.g., 'redis', 'AuthModule').
     * @returns {ILogger} A new `ILogger` instance with the `source` binding.
     */
    withSource(source: string): ILogger;
    /**
     * Creates a new logger instance with a `retention` field bound to it.
     * The provided rules object will be deep-cloned to ensure immutability.
     * @param {LogRetentionRules} rules - A JSON object containing the retention rules.
     * @returns {ILogger} A new `ILogger` instance with the `retention` binding.
     */
    withRetention(rules: LogRetentionRules): ILogger;
    /**
     * Creates a new logger instance with a `transactionId` field bound to it.
     * This is useful for tracking a request across multiple services.
     * @param {string} transactionId - The unique ID of the transaction.
     * @returns {ILogger} A new `ILogger` instance with the `transactionId` binding.
     */
    withTransactionId(transactionId: string): ILogger;
}

/**
 * @interface IContextManager
 * @description The contract for managing asynchronous context.
 */
interface IContextManager {
    /**
     * Configures the context manager with specific options.
     * This should be called once during initialization.
     * @param options The configuration options.
     * @param options.correlationIdHeader The custom header name to use for the correlation ID.
     * @param options.transactionIdHeader The custom header name for the transaction ID.
     */
    configure(options: ContextConfig): void;
    /**
     * Executes a function within a new, isolated asynchronous context.
     * The new context can inherit data from the parent context.
     * @template T The return type of the callback function.
     * @param callback The function to execute within the new context.
     * @returns The return value of the callback function.
     */
    run(fn: ContextCallback): Promise<void>;
    /**
     * Sets a value in the current asynchronous context.
     * @param key The key for the value.
     * @param value The value to store.
     */
    set(key: string, value: ContextValue): void;
    /**
     * Gets a value from the current asynchronous context.
     * @template T The expected type of the value.
     * @param key The key of the value to retrieve.
     * @returns The value associated with the key, or `undefined` if not found.
     */
    get<T = ContextValue>(key: string): T | undefined;
    /**
     * Gets the entire key-value store from the current context.
     * @returns {ContextData} An object containing all context data.
     */
    getAll(): ContextData;
    /**
     * A convenience method to get the correlation ID from the current context.
     * If no correlation ID exists, generates one automatically to ensure tracing continuity.
     * @returns {string} The correlation ID (never undefined).
     */
    getCorrelationId(): string;
    /**
     * Gets the configured HTTP header name used for the correlation ID.
     * @returns {string} The header name.
     */
    getCorrelationIdHeaderName(): string;
    /**
     * Gets the configured HTTP header name used for the transaction ID.
     * @returns {string} The header name.
     */
    getTransactionIdHeaderName(): string;
    /**
     * A convenience method to get the transaction ID from the current context.
     * @returns {string | undefined} The transaction ID, or undefined if not set.
     */
    getTransactionId(): string | undefined;
    /**
     * A convenience method to set the transaction ID in the current context.
     * @param transactionId The transaction ID to set.
     */
    setTransactionId(transactionId: string): void;
    /** Gets the tracing headers to propagate the context (e.g., W3C Trace Context). */
    getTraceContextHeaders(): ContextHeaders;
    /**
     * Gets a filtered context based on the specified log level.
     * This is useful for logging purposes to ensure only relevant context is included.
     * @param level The log level to filter by.
     * @returns A record containing only the context data relevant for the specified level.
     */
    getFilteredContext(level: LogLevel): FilteredContext;
    /**
     * Reconfigures the logging matrix dynamically.
     * This method allows changing which context fields are included in logs
     * without affecting security configurations like masking or log levels.
     * @param newMatrix The new logging matrix configuration
     */
    reconfigureLoggingMatrix(newMatrix: LoggingMatrix): void;
}

/**
 * FILE: src/config.schema.ts
 * DESCRIPTION: Defines the Zod validation schemas for the entire library's configuration.
 * These schemas are the single source of truth for the configuration's structure and types.
 */

/**
 * @description Schema for a single message broker client instance.
 * It validates that a valid `IBrokerAdapter` is provided.
 * @private
 */
declare const brokerInstanceConfigSchema: z.ZodObject<{
    instanceName: z.ZodString;
    adapter: z.ZodType<IBrokerAdapter, z.ZodTypeDef, IBrokerAdapter>;
    /**
     * An array of context keys to propagate as message headers/properties.
     * To propagate all keys, provide an array with a single wildcard: `['*']`.
     * If not provided, only `correlationId` and `transactionId` are propagated by default.
     */
    propagate: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
    /**
     * @deprecated Use `propagate` instead.
     * If true, propagates the entire asynchronous context map as headers.
     * If false (default), only propagates `correlationId` and `transactionId`.
     */
    propagateFullContext: z.ZodOptional<z.ZodBoolean>;
    isDefault: z.ZodOptional<z.ZodBoolean>;
}, "strip", z.ZodTypeAny, {
    instanceName: string;
    adapter: IBrokerAdapter;
    isDefault?: boolean | undefined;
    propagate?: string[] | undefined;
    propagateFullContext?: boolean | undefined;
}, {
    instanceName: string;
    adapter: IBrokerAdapter;
    isDefault?: boolean | undefined;
    propagate?: string[] | undefined;
    propagateFullContext?: boolean | undefined;
}>;
/**
 * @description Schema for the main message broker configuration block.
 */
declare const brokerConfigSchema: z.ZodOptional<z.ZodObject<{
    /** An array of broker client instance configurations. */
    instances: z.ZodArray<z.ZodObject<{
        instanceName: z.ZodString;
        adapter: z.ZodType<IBrokerAdapter, z.ZodTypeDef, IBrokerAdapter>;
        /**
         * An array of context keys to propagate as message headers/properties.
         * To propagate all keys, provide an array with a single wildcard: `['*']`.
         * If not provided, only `correlationId` and `transactionId` are propagated by default.
         */
        propagate: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
        /**
         * @deprecated Use `propagate` instead.
         * If true, propagates the entire asynchronous context map as headers.
         * If false (default), only propagates `correlationId` and `transactionId`.
         */
        propagateFullContext: z.ZodOptional<z.ZodBoolean>;
        isDefault: z.ZodOptional<z.ZodBoolean>;
    }, "strip", z.ZodTypeAny, {
        instanceName: string;
        adapter: IBrokerAdapter;
        isDefault?: boolean | undefined;
        propagate?: string[] | undefined;
        propagateFullContext?: boolean | undefined;
    }, {
        instanceName: string;
        adapter: IBrokerAdapter;
        isDefault?: boolean | undefined;
        propagate?: string[] | undefined;
        propagateFullContext?: boolean | undefined;
    }>, "many">;
    /** The name of the default broker instance to use when no name is provided to `getInstance()`. */
    default: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
    instances: {
        instanceName: string;
        adapter: IBrokerAdapter;
        isDefault?: boolean | undefined;
        propagate?: string[] | undefined;
        propagateFullContext?: boolean | undefined;
    }[];
    default?: string | undefined;
}, {
    instances: {
        instanceName: string;
        adapter: IBrokerAdapter;
        isDefault?: boolean | undefined;
        propagate?: string[] | undefined;
        propagateFullContext?: boolean | undefined;
    }[];
    default?: string | undefined;
}>>;

/**
 * @file src/config.ts
 * @description Defines and exports the configuration types for the library.
 * These types are now explicitly defined for better TypeScript intellisense and autocompletion,
 * while still using Zod schemas for runtime validation.
 */

/**
 * @description The configuration type for a single message broker client instance.
 */
type BrokerInstanceConfig = z.infer<typeof brokerInstanceConfigSchema>;
/**
 * @description The configuration type for the global message broker settings block.
 * `NonNullable` is used to ensure it's always an object, even if optional in the main config.
 */
type SyntropyBrokerConfig = NonNullable<z.infer<typeof brokerConfigSchema>>;

/**
 * FILE: src/brokers/BrokerManager.ts
 * DESCRIPTION:
 * Manages the lifecycle and creation of multiple instrumented broker client instances,
 * following the same pattern as HttpManager and RedisManager.
 */

/**
 * @class BrokerManager
 * @description Manages the lifecycle and creation of multiple instrumented broker client instances.
 * It reads the configuration, creates an `InstrumentedBrokerClient` for each defined
 * instance, and provides a way to retrieve them and shut them down gracefully.
 */
declare class BrokerManager {
    private readonly instances;
    private defaultInstance?;
    private readonly logger;
    private readonly config;
    private readonly contextManager;
    constructor(config: SyntropyBrokerConfig, logger: ILogger, contextManager: IContextManager);
    init(): Promise<void>;
    getInstance(name?: string): InstrumentedBrokerClient;
    shutdown(): Promise<void>;
}

/**
 * @file src/brokers/InstrumentedBrokerClient.ts
 * @description The core instrumentation class. It wraps any `IBrokerAdapter`
 * implementation and adds logging and automatic context propagation for
 * distributed tracing.
 */

/**
 * @class InstrumentedBrokerClient
 * @description Wraps a user-provided broker adapter to automatically handle
 * logging, context propagation, and distributed tracing.
 */
declare class InstrumentedBrokerClient {
    private readonly adapter;
    private readonly logger;
    private readonly contextManager;
    private readonly config;
    readonly instanceName: string;
    /**
     * @constructor
     * @param {IBrokerAdapter} adapter - The concrete broker adapter implementation (e.g., for RabbitMQ, Kafka).
     * @param {ILogger} logger - The logger instance for this client.
     * @param {IContextManager} contextManager - The manager for handling asynchronous contexts.
     * @param {BrokerInstanceConfig} config - The configuration for this specific instance.
     */
    constructor(adapter: IBrokerAdapter, logger: ILogger, contextManager: IContextManager, config: BrokerInstanceConfig);
    /**
     * Establishes a connection to the broker, wrapping the adapter's connect
     * method with logging.
     * @returns {Promise<void>}
     */
    connect(): Promise<void>;
    /**
     * Disconnects from the broker, wrapping the adapter's disconnect method
     * with logging.
     * @returns {Promise<void>}
     */
    disconnect(): Promise<void>;
    /**
     * Publishes a message, automatically injecting the current `correlation-id`
     * from the active context into the message headers.
     * @param {string} topic - The destination topic or routing key for the message.
     * @param {BrokerMessage} message - The message to be published. The `correlation-id`
     * will be added to its headers if not present.
     * @returns {Promise<void>}
     */
    publish(topic: string, message: BrokerMessage): Promise<void>;
    /**
     * Subscribes to a topic. It wraps the user's message handler to automatically
     * create a new asynchronous context for each incoming message. If a `correlation-id`
     * is found in the message headers, it is used to initialize the new context.
     * @param {string} topic - The topic or queue to subscribe to.
     * @param {MessageHandler} handler - The user-provided function to process incoming messages.
     * @returns {Promise<void>}
     */
    subscribe(topic: string, handler: MessageHandler): Promise<void>;
}

export { BrokerManager, InstrumentedBrokerClient };
export type { BrokerMessage, IBrokerAdapter, MessageHandler, MessageLifecycleControls };
