import { trace } from "@opentelemetry/api";
import { validateRetentionConfig } from "../core/archive-config.js";
import { ArchiveScheduler } from "../core/archive-scheduler.js";
import getObservabilityDbPath from "../core/db-path.js";
import { AIGNEObserverOptionsSchema } from "../core/type.js";
import { isBlocklet } from "../core/util.js";
import { initOpenTelemetry } from "../opentelemetry/instrument/init.js";
export class AIGNEObserver {
    storage;
    retentionConfig;
    tracer = trace.getTracer("aigne-tracer");
    processor;
    exporter;
    sdkServerStarted;
    archiveScheduler;
    sdk;
    static exportFn;
    static setExportFn(exportFn) {
        AIGNEObserver.exportFn = exportFn;
    }
    static updateFn;
    static setUpdateFn(updateFn) {
        AIGNEObserver.updateFn = updateFn;
    }
    constructor(options) {
        const parsed = AIGNEObserverOptionsSchema.parse(options);
        this.storage = parsed?.storage ?? (!isBlocklet ? getObservabilityDbPath() : undefined);
        this.retentionConfig = parsed?.retention;
    }
    async serve() {
        this.sdkServerStarted ??= this._serve();
        return this.sdkServerStarted;
    }
    async _serve() {
        if (!this.storage && !isBlocklet) {
            throw new Error("Server storage is not configured");
        }
        const { sdk, spanProcessor, traceExporter } = await initOpenTelemetry({
            dbPath: this.storage,
            exportFn: AIGNEObserver.exportFn,
            updateFn: AIGNEObserver.updateFn,
        });
        this.sdk = sdk;
        this.processor = spanProcessor;
        this.exporter = traceExporter;
        // Initialize and start archive scheduler if retention config provided
        if (this.storage && this.retentionConfig) {
            try {
                const validatedConfig = validateRetentionConfig(this.retentionConfig);
                this.archiveScheduler = new ArchiveScheduler(this.storage, validatedConfig);
                this.archiveScheduler.start();
                console.log("[Observability] Archive scheduler started");
            }
            catch (error) {
                console.error("[Observability] Failed to start archive scheduler:", error);
            }
        }
    }
    async flush(span) {
        await this.processor?.onEnd(span);
        await this.processor?.forceFlush();
    }
    async update(id, data) {
        await this.exporter?.update(id, data);
    }
    async close(contextIds = []) {
        try {
            // Stop archive scheduler
            if (this.archiveScheduler) {
                this.archiveScheduler.stop();
                this.archiveScheduler = undefined;
                console.log("[Observability] Archive scheduler stopped");
            }
            await this.exporter?.shutdown(contextIds);
            this.processor = undefined;
            this.sdk = undefined;
            this.sdkServerStarted = undefined;
        }
        catch (error) {
            console.error("[Observability] Error during shutdown:", error);
        }
    }
}
