import { ConfigurationOption } from 'autotel-edge';

/**
 * Type definitions for @cloudflare/actors integration
 */

/**
 * Actor-specific instrumentation options
 */
interface ActorInstrumentationOptions {
    /**
     * Whether to instrument storage operations (sql queries, etc.)
     * @default true
     */
    instrumentStorage?: boolean;
    /**
     * Whether to instrument alarm operations
     * @default true
     */
    instrumentAlarms?: boolean;
    /**
     * Whether to instrument socket operations
     * @default true
     */
    instrumentSockets?: boolean;
    /**
     * Whether to capture persist events as spans
     * @default true
     */
    capturePersistEvents?: boolean;
    /**
     * Custom span name formatter for lifecycle methods
     */
    spanNameFormatter?: (actorName: string, lifecycle: string) => string;
}
/**
 * Actor-specific configuration
 * Can be a static config object with actors options, or a function that returns config
 */
type ActorConfig = ConfigurationOption & {
    /**
     * Actor-specific instrumentation options
     */
    actors?: ActorInstrumentationOptions;
};
/**
 * Actor lifecycle events that can be traced
 */
type ActorLifecycle = 'init' | 'request' | 'alarm' | 'persist' | 'websocket.connect' | 'websocket.message' | 'websocket.disconnect' | 'websocket.upgrade' | 'destroy';
/**
 * Minimal interface matching @cloudflare/actors Actor class
 * We don't import the actual type to avoid coupling
 */
interface ActorLike {
    name?: string;
    identifier?: string;
    storage?: unknown;
    alarms?: unknown;
    sockets?: unknown;
    fetch?(request: Request): Promise<Response>;
    alarm?(alarmInfo?: unknown): Promise<void>;
}
/**
 * Constructor type for Actor classes
 */
type ActorConstructor<T extends ActorLike = ActorLike> = new (state: DurableObjectState, env: unknown) => T;

/**
 * Actor class instrumentation for @cloudflare/actors
 *
 * Wraps Actor lifecycle methods with OpenTelemetry tracing:
 * - onInit: Traced as 'actor.lifecycle': 'init'
 * - onRequest: Traced with full HTTP semantics
 * - onAlarm: Traced as 'actor.lifecycle': 'alarm'
 * - onPersist: Traced as 'actor.lifecycle': 'persist'
 * - WebSocket methods: Traced with socket semantics
 */

/**
 * Instrument an Actor class for comprehensive OpenTelemetry tracing
 *
 * This wraps the Actor class to automatically trace all lifecycle methods:
 * - onInit: Actor initialization
 * - onRequest: HTTP request handling
 * - onAlarm: Alarm triggers
 * - onPersist: Property persistence events
 * - WebSocket methods: Connection, message, disconnect
 *
 * It also optionally instruments:
 * - actor.storage: SQL queries and storage operations
 * - actor.alarms: Alarm scheduling operations
 * - actor.sockets: WebSocket operations
 *
 * @example
 * ```typescript
 * import { Actor } from '@cloudflare/actors'
 * import { instrumentActor } from 'autotel-cloudflare/actors'
 *
 * class Counter extends Actor<Env> {
 *   protected onInit() {
 *     console.log('Counter initialized')
 *   }
 *
 *   protected onRequest(request: Request) {
 *     return new Response('count: 42')
 *   }
 * }
 *
 * // Wrap the class
 * export const InstrumentedCounter = instrumentActor(Counter, (env: Env) => ({
 *   service: { name: 'counter-actor' },
 *   exporter: { url: env.OTLP_ENDPOINT },
 *   actors: {
 *     instrumentStorage: true,
 *     capturePersistEvents: true
 *   }
 * }))
 * ```
 *
 * @param actorClass - The Actor class to instrument
 * @param config - Configuration (static object or function)
 * @returns Instrumented Actor class
 */
declare function instrumentActor<C extends ActorConstructor>(actorClass: C, config: ActorConfig | ((env: unknown, trigger?: unknown) => ActorConfig)): C;

/**
 * Traced handler wrapper for @cloudflare/actors
 *
 * Wraps the Actors handler() to provide:
 * - Root span for the entire request lifecycle
 * - Actor name extraction and correlation
 * - Request routing tracing
 */

/**
 * Worker handler type matching @cloudflare/actors output
 */
interface WorkerHandler<E = unknown> {
    fetch(request: Request, env: E, ctx: ExecutionContext): Promise<Response>;
}
/**
 * Create a traced handler that combines Actor instrumentation with request tracing
 *
 * This is an all-in-one wrapper that:
 * 1. Initializes telemetry for the Worker
 * 2. Creates a root span for each incoming request
 * 3. Extracts the Actor name using `nameFromRequest`
 * 4. Instruments the Actor class with lifecycle tracing
 * 5. Routes the request to the instrumented Actor
 *
 * @example
 * ```typescript
 * import { Actor } from '@cloudflare/actors'
 * import { tracedHandler } from 'autotel-cloudflare/actors'
 *
 * class MyActor extends Actor<Env> {
 *   protected onRequest(request: Request) {
 *     return new Response('Hello!')
 *   }
 * }
 *
 * // Export the Actor class and use tracedHandler
 * export { MyActor }
 * export default tracedHandler(MyActor, (env) => ({
 *   service: { name: 'my-actor-service' },
 *   exporter: { url: env.OTLP_ENDPOINT }
 * }))
 * ```
 *
 * @param actorClass - The Actor class to handle requests
 * @param config - Configuration (static object or function)
 * @returns A Worker handler with full tracing
 */
declare function tracedHandler<E, A extends ActorLike>(actorClass: ActorConstructor<A> & {
    nameFromRequest?(request: Request): Promise<string | undefined>;
    configuration?(request: Request): {
        locationHint?: DurableObjectLocationHint;
    };
}, config: ActorConfig | ((env: E, trigger?: unknown) => ActorConfig)): WorkerHandler<E>;
/**
 * Alternative: Create a handler wrapper that uses the existing @cloudflare/actors handler
 *
 * This is useful if you want to use the original handler() but add tracing around it.
 *
 * @example
 * ```typescript
 * import { Actor, handler } from '@cloudflare/actors'
 * import { wrapHandler } from 'autotel-cloudflare/actors'
 *
 * class MyActor extends Actor<Env> {}
 *
 * export { MyActor }
 * export default wrapHandler(handler(MyActor), (env) => ({
 *   service: { name: 'my-service' }
 * }))
 * ```
 */
declare function wrapHandler<E>(originalHandler: WorkerHandler<E>, config: ActorConfig | ((env: E, trigger?: unknown) => ActorConfig)): WorkerHandler<E>;

/**
 * Actor storage instrumentation
 *
 * Traces operations on actor.storage including SQL queries
 */

/**
 * Instrument Actor storage for tracing
 *
 * Captures:
 * - SQL query operations
 * - Key-value operations (if available)
 */
declare function instrumentActorStorage(storage: unknown, actorInstance: ActorLike, actorClass: object): unknown;

/**
 * Actor alarms instrumentation
 *
 * Traces operations on actor.alarms
 */

/**
 * Instrument Actor alarms for tracing
 *
 * Captures:
 * - set: Schedule a single alarm
 * - setMultiple: Schedule multiple alarms
 * - cancel: Cancel an alarm
 * - cancelAll: Cancel all alarms
 */
declare function instrumentActorAlarms(alarms: unknown, actorInstance: ActorLike, actorClass: object): unknown;

/**
 * Actor sockets instrumentation
 *
 * Traces operations on actor.sockets
 */

/**
 * Instrument Actor sockets for tracing
 *
 * Captures:
 * - acceptWebSocket: Accept an incoming WebSocket connection
 * - broadcast: Send message to all connected sockets
 * - send: Send message to a specific socket
 */
declare function instrumentActorSockets(sockets: unknown, actorInstance: ActorLike, actorClass: object): unknown;

export { type ActorConfig, type ActorInstrumentationOptions, type ActorLifecycle, instrumentActor, instrumentActorAlarms, instrumentActorSockets, instrumentActorStorage, tracedHandler, wrapHandler };
