import * as _opentelemetry_api from '@opentelemetry/api';
import { Span } from '@opentelemetry/api';
import { Sampler } from './sampling.cjs';
import { T as TraceContext } from './trace-context-t5X1AP-e.cjs';
import './logger.cjs';
import 'pino';

/**
 * Helper type to extract function signature from factory pattern
 * This helps TypeScript infer types correctly for factory functions
 */
type ExtractFunctionSignature<T> = T extends (ctx: TraceContext) => infer F ? F extends (...args: infer Args) => infer Return ? (...args: Args) => Return : never : never;
/**
 * Helper type to exclude functions that return functions from immediate execution overloads
 */
type ExcludeFactoryReturn<T> = T extends (ctx: TraceContext) => infer F ? F extends (...args: any[]) => any ? never : T : T;
/**
 * Common options for functional tracing
 */
interface TracingOptions<TArgs extends unknown[] = unknown[], TReturn = unknown> {
    /**
     * Span name (highest priority)
     * If provided, this is used as the span name
     */
    name?: string;
    /**
     * Service name (used to compose final span name)
     * If name not provided, span name becomes: ${serviceName}.${functionName}
     */
    serviceName?: string;
    /**
     * Sampling strategy
     * @default AlwaysSampler
     */
    sampler?: Sampler;
    /**
     * Enable metrics collection (counter, histogram)
     * @default false
     */
    withMetrics?: boolean;
    /**
     * Extract attributes from function arguments
     */
    attributesFromArgs?: (args: TArgs) => Record<string, unknown>;
    /**
     * Extract attributes from function result
     */
    attributesFromResult?: (result: TReturn) => Record<string, unknown>;
    /**
     * Start a new root span instead of creating a child
     * Useful for serverless entry points
     * @default false
     */
    startNewRoot?: boolean;
    /**
     * Flush events queue when span ends
     * Only flushes on root spans (to avoid excessive flushing)
     * @default true
     */
    flushOnRootSpanEnd?: boolean;
    /**
     * Span kind for semantic convention compliance
     * Used for messaging (PRODUCER/CONSUMER), HTTP (CLIENT/SERVER), etc.
     * @default SpanKind.INTERNAL
     */
    spanKind?: _opentelemetry_api.SpanKind;
}
/**
 * Options for instrument() batch instrumentation
 */
interface InstrumentOptions<T extends Record<string, InstrumentableFunction> = Record<string, InstrumentableFunction>> extends TracingOptions {
    /** Functions to instrument */
    functions: T;
    /**
     * Per-function configuration overrides
     */
    overrides?: Record<string, Partial<TracingOptions>>;
    /**
     * Functions to skip (won't be instrumented)
     * Supports:
     * - String keys: 'functionName'
     * - RegExp: /^_internal/
     * - Predicate: (key, fn) => boolean
     *
     * By default, functions starting with _ are skipped
     */
    skip?: (string | RegExp | ((key: string, fn: Function) => boolean))[];
}
type InstrumentableFunction<TArgs extends unknown[] = unknown[], TReturn = unknown> = ((...args: TArgs) => TReturn | Promise<TReturn>) & {
    displayName?: string;
    name?: string;
};
/**
 * Context object that lazily evaluates the active span on property access
 *
 * Access trace context directly without function call syntax.
 *
 * @example
 * ```typescript
 * import { trace, ctx } from 'autotel'
 *
 * export const createUser = trace(async (data) => {
 *   // Direct property access - no function call!
 *   if (ctx.traceId) {
 *     ctx.setAttribute('user.id', data.id)
 *     console.log('Trace:', ctx.traceId)
 *   }
 * })
 * ```
 */
declare const ctx: {};
/**
 * Approach 1: trace() - Zero-ceremony HOF
 *
 * Wrap a single function with automatic tracing.
 * The function receives a context object as the first parameter.
 *
 * Supports two patterns:
 * 1. **Factory pattern** - Returns a traced function: `trace(ctx => (...args) => result)`
 * 2. **Immediate execution** - Executes immediately with tracing: `trace(ctx => result)`
 *
 * @example Auto-inferred name - Plain function
 * ```typescript
 * export const createUser = trace(async (data) => {
 *   return await db.users.create(data)
 * })
 * // → Traced as "createUser"
 * ```
 *
 * @example Auto-inferred name - Factory pattern (with ctx access)
 * ```typescript
 * export const createUser = trace(ctx => async (data) => {
 *   ctx.setAttribute('user.id', data.id)
 *   return await db.users.create(data)
 * })
 * // → Traced as "createUser", returns wrapped function
 * ```
 *
 * @example Immediate execution - Execute once with tracing
 * ```typescript
 * // Wraps an existing function and executes immediately
 * function timed<T>(fn: () => Promise<T>): Promise<T> {
 *   return trace(async (ctx) => {
 *     ctx.setAttribute('operation', 'timed')
 *     return await fn()
 *   })
 * }
 * // → Executes immediately, returns result directly
 * ```
 *
 * @example Custom name - Plain function
 * ```typescript
 * export const createUser = trace('user.create', async (data) => {
 *   return await db.users.create(data)
 * })
 * // → Traced as "user.create"
 * ```
 *
 * @example Custom name - Factory pattern
 * ```typescript
 * export const createUser = trace('user.create', ctx => async (data) => {
 *   ctx.setAttribute('user.id', data.id)
 *   return await db.users.create(data)
 * })
 * // → Traced as "user.create"
 * ```
 *
 * @example Custom name - Immediate execution
 * ```typescript
 * const result = trace('fetch.user', async (ctx) => {
 *   ctx.setAttribute('userId', '123')
 *   return await fetchUser('123')
 * })
 * // → Executes immediately with span name "fetch.user"
 * ```
 *
 * @example Full options - Plain function
 * ```typescript
 * export const createUser = trace({
 *   name: 'user.create',
 *   sampler: new AdaptiveSampler(),
 *   withMetrics: true
 * }, async (data) => {
 *   return await db.users.create(data)
 * })
 * ```
 *
 * @example Full options - Factory pattern
 * ```typescript
 * export const createUser = trace({
 *   name: 'user.create',
 *   sampler: new AdaptiveSampler(),
 *   withMetrics: true
 * }, ctx => async (data) => {
 *   ctx.setAttribute('user.id', data.id)
 *   return await db.users.create(data)
 * })
 * ```
 */
declare function trace<TBaggage extends Record<string, unknown> | undefined = undefined, TReturn = unknown>(fn: (ctx: TraceContext<TBaggage>) => TReturn): TReturn;
declare function trace<TBaggage extends Record<string, unknown> | undefined = undefined>(fnFactory: (ctx: TraceContext<TBaggage>) => () => unknown): () => unknown;
declare function trace<TBaggage extends Record<string, unknown> | undefined = undefined, TArgs extends unknown[] = unknown[], TReturn = unknown>(fnFactory: (ctx: TraceContext<TBaggage>) => (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
declare function trace<TReturn = unknown>(fnFactory: (ctx: TraceContext) => () => TReturn): () => TReturn;
declare function trace<TFactory extends (ctx: TraceContext) => (...args: unknown[]) => unknown>(fnFactory: TFactory): ExtractFunctionSignature<TFactory>;
declare function trace<TArgs extends unknown[], TReturn = unknown>(fnFactory: (ctx: TraceContext) => (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
declare function trace<TReturn = unknown>(fn: () => TReturn): () => TReturn;
declare function trace<TArgs extends unknown[], TReturn = unknown>(fn: (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
declare function trace<TReturn = unknown>(name: string, fn: ExcludeFactoryReturn<(ctx: TraceContext) => TReturn>): TReturn;
declare function trace<TReturn = unknown>(name: string, fnFactory: (ctx: TraceContext) => () => TReturn): () => TReturn;
declare function trace<TArgs extends unknown[], TReturn>(name: string, fnFactory: (ctx: TraceContext) => (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
declare function trace<TFactory extends (ctx: TraceContext) => (...args: unknown[]) => unknown>(name: string, fnFactory: TFactory): ExtractFunctionSignature<TFactory>;
declare function trace<TArgs extends unknown[] = unknown[], TReturn = unknown>(name: string, fnFactory: (ctx: TraceContext) => (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
declare function trace<TArgs extends unknown[] = unknown[], TReturn = unknown>(name: string, fn: (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
declare function trace<TReturn = unknown>(options: TracingOptions<[], TReturn>, fn: (ctx: TraceContext) => TReturn): TReturn;
declare function trace<TReturn = unknown>(options: TracingOptions<[], TReturn>, fnFactory: (ctx: TraceContext) => () => TReturn): () => TReturn;
declare function trace<TArgs extends unknown[], TReturn>(options: TracingOptions<TArgs, TReturn>, fnFactory: (ctx: TraceContext) => (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
declare function trace<TArgs extends unknown[] = unknown[], TReturn = unknown>(options: TracingOptions<TArgs, TReturn>, fnFactory: (ctx: TraceContext) => (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
declare function trace<TArgs extends unknown[] = unknown[], TReturn = unknown>(options: TracingOptions<TArgs, TReturn>, fn: (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
declare function trace<TReturn = unknown>(fn: (ctx: TraceContext) => Promise<TReturn>): Promise<TReturn>;
declare function trace(fnFactory: (ctx: TraceContext) => () => Promise<unknown>): () => Promise<unknown>;
declare function trace<TArgs extends unknown[], TReturn>(fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>): (...args: TArgs) => Promise<TReturn>;
declare function trace<TReturn = unknown>(fnFactory: (ctx: TraceContext) => () => Promise<TReturn>): () => Promise<TReturn>;
declare function trace<TFactory extends (ctx: TraceContext) => (...args: unknown[]) => Promise<unknown>>(fnFactory: TFactory): ExtractFunctionSignature<TFactory>;
declare function trace<TArgs extends unknown[] = unknown[], TReturn = unknown>(fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>): (...args: TArgs) => Promise<TReturn>;
declare function trace<TReturn = unknown>(fn: () => Promise<TReturn>): () => Promise<TReturn>;
declare function trace<TArgs extends unknown[] = unknown[], TReturn = unknown>(fn: (...args: TArgs) => Promise<TReturn>): (...args: TArgs) => Promise<TReturn>;
declare function trace<TReturn = unknown>(name: string, fn: ExcludeFactoryReturn<(ctx: TraceContext) => Promise<TReturn>>): Promise<TReturn>;
declare function trace<TReturn = unknown>(name: string, fnFactory: (ctx: TraceContext) => () => Promise<TReturn>): () => Promise<TReturn>;
declare function trace<TArgs extends unknown[], TReturn>(name: string, fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>): (...args: TArgs) => Promise<TReturn>;
declare function trace<TFactory extends (ctx: TraceContext) => (...args: unknown[]) => Promise<unknown>>(name: string, fnFactory: TFactory): ExtractFunctionSignature<TFactory>;
declare function trace<TArgs extends unknown[] = unknown[], TReturn = unknown>(name: string, fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>): (...args: TArgs) => Promise<TReturn>;
declare function trace<TArgs extends unknown[] = unknown[], TReturn = unknown>(name: string, fn: (...args: TArgs) => Promise<TReturn>): (...args: TArgs) => Promise<TReturn>;
declare function trace<TReturn = unknown>(options: TracingOptions<[], TReturn>, fn: (ctx: TraceContext) => Promise<TReturn>): Promise<TReturn>;
declare function trace<TReturn = unknown>(options: TracingOptions<[], TReturn>, fnFactory: (ctx: TraceContext) => () => Promise<TReturn>): () => Promise<TReturn>;
declare function trace<TArgs extends unknown[], TReturn>(options: TracingOptions<TArgs, TReturn>, fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>): (...args: TArgs) => Promise<TReturn>;
declare function trace<TArgs extends unknown[] = unknown[], TReturn = unknown>(options: TracingOptions<TArgs, TReturn>, fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>): (...args: TArgs) => Promise<TReturn>;
declare function trace<TArgs extends unknown[] = unknown[], TReturn = unknown>(options: TracingOptions<TArgs, TReturn>, fn: (...args: TArgs) => Promise<TReturn>): (...args: TArgs) => Promise<TReturn>;
/**
 * Approach 2: withTracing() - Middleware-style composable wrapper
 *
 * Returns a HOF that wraps functions with tracing.
 * Perfect for composition and reusable configuration.
 *
 * @example Standard usage
 * ```typescript
 * export const createUser = withTracing({
 *   name: 'user.create'
 * })(ctx => async (data) => {
 *   ctx.setAttribute('user.id', data.id)
 *   return await db.users.create(data)
 * })
 * ```
 *
 * @example Composable
 * ```typescript
 * const trace = withTracing({ serviceName: 'user' })
 *
 * export const createUser = trace(ctx => async (data) => { })
 * export const updateUser = trace(ctx => async (id, data) => { })
 * ```
 *
 * @example With other middleware
 * ```typescript
 * export const createUser = compose(
 *   withAuth({ role: 'admin' }),
 *   withTracing({ name: 'user.create' }),
 *   withRateLimit({ max: 100 })
 * )(ctx => async (data) => { })
 * ```
 */
declare function withTracing<TArgs extends unknown[] = unknown[], TReturn = unknown>(options?: TracingOptions<TArgs, TReturn>): (fnFactory: (ctx: TraceContext) => (...args: TArgs) => TReturn | Promise<TReturn>) => (...args: TArgs) => TReturn | Promise<TReturn>;
/**
 * Approach 3: instrument() - Batch auto-instrumentation
 *
 * Instrument an entire module/object at once.
 * Closest to @Instrumented decorator pattern.
 *
 * @example Basic usage
 * ```typescript
 * export default instrument({
 *   functions: {
 *     createUser: async (data) => { },
 *     updateUser: async (id, data) => { },
 *     deleteUser: async (id) => { }
 *   },
 *   serviceName: 'user',
 *   sampler: new AdaptiveSampler()
 * })
 * // → Traced as "user.createUser", "user.updateUser", "user.deleteUser"
 * ```
 *
 * @example Per-function overrides
 * ```typescript
 * export default instrument({
 *   functions: {
 *     createUser: async (data) => { },
 *     deleteUser: async (id) => { }
 *   },
 *   serviceName: 'user',
 *   overrides: {
 *     deleteUser: {
 *       sampler: new AlwaysSampler(),
 *       withMetrics: true
 *     }
 *   }
 * })
 * ```
 *
 * @example Skip functions
 * ```typescript
 * export default instrument({
 *   functions: {
 *     createUser: async (data) => { },
 *     _internal: async () => { }, // Auto-skipped (_-prefix)
 *     deleteUser: async (id) => { }
 *   },
 *   serviceName: 'user',
 *   skip: [/^test/, (key) => key.includes('debug')]
 * })
 * ```
 */
declare function instrument<T extends Record<string, InstrumentableFunction>>(options: InstrumentOptions<T>): T;
/**
 * Options for span() function
 */
interface SpanOptions {
    /** Span name */
    name: string;
    /** Attributes to set on the span */
    attributes?: Record<string, string | number | boolean>;
}
/**
 * Execute a function within a named span
 *
 * Useful for adding tracing to specific code blocks without wrapping
 * the entire function. Supports both synchronous and asynchronous functions.
 *
 * @example
 * ```typescript
 * // Async function
 * async function processOrder(order: Order) {
 *   await span({
 *     name: 'payment.charge',
 *     attributes: { amount: order.total }
 *   }, async (span) => {
 *     await chargeCustomer(order);
 *   })
 * }
 *
 * // Sync function
 * function calculateTotal(items: Item[]) {
 *   return span({
 *     name: 'calculateTotal',
 *     attributes: { itemCount: items.length }
 *   }, (span) => {
 *     return items.reduce((sum, item) => sum + item.price, 0);
 *   })
 * }
 * ```
 */
declare function span<T = unknown>(options: SpanOptions, fn: (span: Span) => T): T;
declare function span<T = unknown>(options: SpanOptions, fn: (span: Span) => Promise<T>): Promise<T>;
/**
 * Options for withNewContext() function
 */
interface WithNewContextOptions<T = unknown> {
    /** Function to execute in new root context */
    fn: () => Promise<T>;
}
/**
 * Execute a function in a new root context (prevents span propagation)
 *
 * Useful when you want to start a completely new trace without
 * parent-child relationships.
 *
 * @example
 * ```typescript
 * async function handleWebhook(payload: WebhookPayload) {
 *   // This creates a new root trace, not connected to the HTTP request trace
 *   await withNewContext({
 *     fn: async () => {
 *       await trace(ctx => async () => {
 *         await processWebhookPayload(payload)
 *       })()
 *     }
 *   })
 * }
 * ```
 */
declare function withNewContext<T = unknown>(options: WithNewContextOptions<T>): Promise<T>;
/**
 * Options for withBaggage() function
 */
interface WithBaggageOptions<T = unknown> {
    /** Baggage entries to set (key-value pairs) */
    baggage: Record<string, string>;
    /** Function to execute with the updated baggage */
    fn: () => T | Promise<T>;
}
/**
 * Execute a function with updated baggage entries
 *
 * Baggage is immutable in OpenTelemetry, so this helper creates a new context
 * with the specified baggage entries and runs the function within that context.
 * All child spans created within the function will inherit the baggage.
 *
 * @example Setting baggage for downstream services
 * ```typescript
 * import { trace, withBaggage } from 'autotel';
 *
 * export const createOrder = trace((ctx) => async (order: Order) => {
 *   // Set baggage that will be propagated to downstream HTTP calls
 *   return await withBaggage({
 *     baggage: {
 *       'tenant.id': order.tenantId,
 *       'user.id': order.userId,
 *     },
 *     fn: async () => {
 *       // This HTTP call will include the baggage in headers
 *       await fetch('/api/charge', {
 *         method: 'POST',
 *         body: JSON.stringify(order),
 *       });
 *     },
 *   });
 * });
 * ```
 *
 * @example Using with existing baggage
 * ```typescript
 * export const processOrder = trace((ctx) => async (order: Order) => {
 *   // Read existing baggage
 *   const tenantId = ctx.getBaggage('tenant.id');
 *
 *   // Add additional baggage entries
 *   return await withBaggage({
 *     baggage: {
 *       'order.id': order.id,
 *       'order.amount': String(order.amount),
 *     },
 *     fn: async () => {
 *       await charge(order);
 *     },
 *   });
 * });
 * ```
 */
declare function withBaggage<T = unknown>(options: WithBaggageOptions<T>): T | Promise<T>;

export { type InstrumentOptions, type SpanOptions, TraceContext, type TracingOptions, type WithBaggageOptions, type WithNewContextOptions, ctx, instrument, span, trace, withBaggage, withNewContext, withTracing };
