import { Link, SpanContext } from '@opentelemetry/api';
import { OutOfOrderInfo, RebalanceEvent } from './messaging.cjs';
import './trace-context-t5X1AP-e.cjs';

/**
 * Testing utilities for messaging instrumentation
 *
 * Provides mock producers, consumers, and assertion helpers
 * for testing event-driven code with Autotel's messaging module.
 *
 * @example Basic test setup
 * ```typescript
 * import { createMessagingTestHarness } from 'autotel/messaging-testing';
 *
 * describe('Order processing', () => {
 *   const harness = createMessagingTestHarness();
 *
 *   beforeEach(() => harness.reset());
 *   afterAll(() => harness.shutdown());
 *
 *   it('should process order and publish event', async () => {
 *     await processOrder({ id: 'order-123' });
 *
 *     harness.assertProducerCalled('orders', {
 *       messageCount: 1,
 *       hasTraceHeaders: true,
 *     });
 *   });
 * });
 * ```
 *
 * @module
 */

/**
 * Recorded producer call
 */
interface RecordedProducerCall {
    /** Destination (topic/queue) */
    destination: string;
    /** System (kafka, sqs, etc.) */
    system: string;
    /** Message payload */
    payload: unknown;
    /** Headers injected */
    headers: Record<string, string>;
    /** Timestamp of call */
    timestamp: number;
    /** Trace ID from headers */
    traceId?: string;
    /** Span ID from headers */
    spanId?: string;
}
/**
 * Recorded consumer call
 */
interface RecordedConsumerCall {
    /** Destination (topic/queue) */
    destination: string;
    /** System (kafka, sqs, etc.) */
    system: string;
    /** Consumer group */
    consumerGroup?: string;
    /** Message payload */
    payload: unknown;
    /** Headers extracted */
    headers?: Record<string, string>;
    /** Timestamp of call */
    timestamp: number;
    /** Producer links extracted */
    producerLinks: Link[];
    /** Whether message was duplicate */
    isDuplicate: boolean;
    /** Out of order info if detected */
    outOfOrderInfo: OutOfOrderInfo | null;
    /** DLQ reason if routed to DLQ */
    dlqReason?: string;
    /** Retry attempt number */
    retryAttempt?: number;
}
/**
 * Recorded rebalance event
 */
interface RecordedRebalanceEvent extends RebalanceEvent {
    /** Destination (topic) */
    destination: string;
    /** Consumer group */
    consumerGroup: string;
}
/**
 * Mock message for testing
 */
interface MockMessage<T = unknown> {
    /** Message payload */
    payload: T;
    /** Headers */
    headers?: Record<string, string>;
    /** Offset/sequence number */
    offset?: number;
    /** Partition */
    partition?: number;
    /** Key */
    key?: string;
    /** Message ID */
    messageId?: string;
    /** Timestamp */
    timestamp?: number;
}
/**
 * Producer assertion options
 */
interface ProducerAssertionOptions {
    /** Expected number of messages */
    messageCount?: number;
    /** Whether trace headers should be present */
    hasTraceHeaders?: boolean;
    /** Expected destination */
    destination?: string;
    /** Custom matcher for payload */
    payloadMatcher?: (payload: unknown) => boolean;
    /** Expected trace ID */
    traceId?: string;
}
/**
 * Consumer assertion options
 */
interface ConsumerAssertionOptions {
    /** Expected number of messages processed */
    messageCount?: number;
    /** Whether producer links should be present */
    hasProducerLinks?: boolean;
    /** Expected destination */
    destination?: string;
    /** Expected consumer group */
    consumerGroup?: string;
    /** Whether any messages were duplicates */
    hasDuplicates?: boolean;
    /** Whether any messages were out of order */
    hasOutOfOrder?: boolean;
    /** Whether any messages went to DLQ */
    hasDLQ?: boolean;
}
/**
 * Messaging test harness
 */
interface MessagingTestHarness {
    /** All recorded producer calls */
    producerCalls: RecordedProducerCall[];
    /** All recorded consumer calls */
    consumerCalls: RecordedConsumerCall[];
    /** All recorded rebalance events */
    rebalanceEvents: RecordedRebalanceEvent[];
    /**
     * Record a producer call
     */
    recordProducerCall(call: Omit<RecordedProducerCall, 'timestamp'>): void;
    /**
     * Record a consumer call
     */
    recordConsumerCall(call: Omit<RecordedConsumerCall, 'timestamp'>): void;
    /**
     * Record a rebalance event
     */
    recordRebalanceEvent(event: RecordedRebalanceEvent): void;
    /**
     * Create a mock message with trace headers
     */
    createMockMessage<T>(payload: T, options?: Partial<MockMessage<T>>): MockMessage<T>;
    /**
     * Create mock trace headers
     */
    createMockTraceHeaders(traceId?: string, spanId?: string): Record<string, string>;
    /**
     * Assert producer was called with expected options
     */
    assertProducerCalled(destination: string, options?: ProducerAssertionOptions): void;
    /**
     * Assert producer was not called
     */
    assertProducerNotCalled(destination?: string): void;
    /**
     * Assert consumer processed messages with expected options
     */
    assertConsumerProcessed(destination: string, options?: ConsumerAssertionOptions): void;
    /**
     * Assert consumer was not called
     */
    assertConsumerNotCalled(destination?: string): void;
    /**
     * Assert rebalance occurred
     */
    assertRebalanceOccurred(destination: string, type: RebalanceEvent['type'], partitionCount?: number): void;
    /**
     * Get producer calls for destination
     */
    getProducerCalls(destination?: string): RecordedProducerCall[];
    /**
     * Get consumer calls for destination
     */
    getConsumerCalls(destination?: string): RecordedConsumerCall[];
    /**
     * Get the last producer call
     */
    getLastProducerCall(destination?: string): RecordedProducerCall | undefined;
    /**
     * Get the last consumer call
     */
    getLastConsumerCall(destination?: string): RecordedConsumerCall | undefined;
    /**
     * Reset all recorded calls
     */
    reset(): void;
    /**
     * Shutdown the harness
     */
    shutdown(): void;
}
/**
 * Create a messaging test harness
 *
 * Provides utilities for recording and asserting on producer/consumer calls
 * during testing.
 *
 * @example
 * ```typescript
 * const harness = createMessagingTestHarness();
 *
 * // In your test setup
 * beforeEach(() => harness.reset());
 *
 * // In your tests
 * it('should publish order event', async () => {
 *   await orderService.createOrder({ id: '123' });
 *
 *   harness.assertProducerCalled('orders', {
 *     messageCount: 1,
 *     hasTraceHeaders: true,
 *   });
 *
 *   const lastCall = harness.getLastProducerCall('orders');
 *   expect(lastCall?.payload).toMatchObject({ orderId: '123' });
 * });
 * ```
 */
declare function createMessagingTestHarness(): MessagingTestHarness;
/**
 * Mock message broker for testing
 */
interface MockMessageBroker {
    /** Topics/queues in the broker */
    topics: Map<string, MockMessage[]>;
    /**
     * Publish a message to a topic
     */
    publish(topic: string, message: MockMessage): void;
    /**
     * Consume messages from a topic
     */
    consume(topic: string, count?: number): MockMessage[];
    /**
     * Peek at messages without consuming
     */
    peek(topic: string, count?: number): MockMessage[];
    /**
     * Get message count for topic
     */
    getMessageCount(topic: string): number;
    /**
     * Clear all messages
     */
    clear(topic?: string): void;
    /**
     * Create a topic
     */
    createTopic(topic: string): void;
    /**
     * Delete a topic
     */
    deleteTopic(topic: string): void;
    /**
     * List all topics
     */
    listTopics(): string[];
}
/**
 * Create a mock message broker for testing
 *
 * Simulates a message broker (Kafka, SQS, RabbitMQ, etc.) for unit testing.
 *
 * @example
 * ```typescript
 * const broker = createMockMessageBroker();
 *
 * // Producer publishes
 * broker.publish('orders', { payload: { orderId: '123' }, headers: {} });
 *
 * // Consumer receives
 * const messages = broker.consume('orders');
 * expect(messages).toHaveLength(1);
 * expect(messages[0].payload).toEqual({ orderId: '123' });
 * ```
 */
declare function createMockMessageBroker(): MockMessageBroker;
/**
 * Extract trace ID from traceparent header
 */
declare function extractTraceIdFromHeader(traceparent: string): string | null;
/**
 * Extract span ID from traceparent header
 */
declare function extractSpanIdFromHeader(traceparent: string): string | null;
/**
 * Create a mock span context
 */
declare function createMockSpanContext(traceId?: string, spanId?: string): SpanContext;
/**
 * Create a mock link to a producer span
 */
declare function createMockProducerLink(traceId?: string, spanId?: string): Link;
/**
 * Create a batch of mock messages
 */
declare function createMockMessageBatch<T>(payloads: T[], options?: {
    startOffset?: number;
    partition?: number;
    addTraceHeaders?: boolean;
    traceId?: string;
}): MockMessage<T>[];
/**
 * Create a rebalance scenario
 */
declare function createRebalanceScenario(topic: string, consumerGroup: string, partitions: number[]): {
    assignEvent: RecordedRebalanceEvent;
    revokeEvent: RecordedRebalanceEvent;
};
/**
 * Create an out-of-order scenario
 */
declare function createOutOfOrderScenario<T>(payloads: T[], outOfOrderIndices: number[]): MockMessage<T>[];
/**
 * Create a duplicate message scenario
 */
declare function createDuplicateScenario<T>(payloads: T[], duplicateIndices: number[]): MockMessage<T>[];

export { type ConsumerAssertionOptions, type MessagingTestHarness, type MockMessage, type MockMessageBroker, type ProducerAssertionOptions, type RecordedConsumerCall, type RecordedProducerCall, type RecordedRebalanceEvent, createDuplicateScenario, createMessagingTestHarness, createMockMessageBatch, createMockMessageBroker, createMockProducerLink, createMockSpanContext, createOutOfOrderScenario, createRebalanceScenario, extractSpanIdFromHeader, extractTraceIdFromHeader };
