/**
 * OpenTelemetry integration for end-to-end distributed tracing
 * Traces: HTTP request → service → DB → audit enqueue → poller → final write
 *
 * Note: This is a placeholder implementation. To enable actual distributed tracing,
 * install @opentelemetry/api and configure an OpenTelemetry SDK (e.g., @opentelemetry/sdk-node)
 */

export class AuditTracer {
	private static tracer: any = null;

	/**
	 * Initialize the tracer with OpenTelemetry SDK
	 * Call this during application startup
	 */
	static initialize(tracer: any) {
		this.tracer = tracer;
	}

	/**
	 * Create span for audit event enqueue
	 */
	static async traceEnqueue(params: {
		action: string;
		module: string;
		requestId: string;
		traceId: string;
	}, callback: () => Promise<any>) {
		// If tracer not initialized, just execute callback
		if (!this.tracer) {
			return callback();
		}

		const span = this.tracer.startSpan('audit.enqueue', {
			attributes: {
				'audit.action': params.action,
				'audit.module': params.module,
				'audit.request_id': params.requestId,
				'audit.trace_id': params.traceId,
			},
		});

		try {
			const result = await callback();
			span.setStatus({ code: 1 }); // OK
			return result;
		} catch (error) {
			span.recordException(error as Error);
			span.setStatus({ code: 2, message: (error as Error).message }); // ERROR
			throw error;
		} finally {
			span.end();
		}
	}

	/**
	 * Create span for outbox poller processing
	 */
	static async tracePollProcessing(eventCount: number, callback: () => Promise<any>) {
		// If tracer not initialized, just execute callback
		if (!this.tracer) {
			return callback();
		}

		const span = this.tracer.startSpan('audit.poller.process', {
			attributes: {
				'audit.batch_size': eventCount,
			},
		});

		try {
			const result = await callback();
			span.setStatus({ code: 1 }); // OK
			return result;
		} catch (error) {
			span.recordException(error as Error);
			span.setStatus({ code: 2, message: (error as Error).message }); // ERROR
			throw error;
		} finally {
			span.end();
		}
	}

	/**
	 * Create span for audit log write
	 */
	static async traceWrite(params: {
		eventType: string;
		outboxEventId: string;
	}, callback: () => Promise<any>) {
		// If tracer not initialized, just execute callback
		if (!this.tracer) {
			return callback();
		}

		const span = this.tracer.startSpan('audit.write', {
			attributes: {
				'audit.event_type': params.eventType,
				'audit.outbox_event_id': params.outboxEventId,
			},
		});

		try {
			const result = await callback();
			span.setStatus({ code: 1 }); // OK
			return result;
		} catch (error) {
			span.recordException(error as Error);
			span.setStatus({ code: 2, message: (error as Error).message }); // ERROR
			throw error;
		} finally {
			span.end();
		}
	}
}

export default AuditTracer;
