/**
 * HTTP Endpoint Logger
 * Sends logs to an external HTTP logging service.
 *
 * Enabled via env:
 *  - HTTP_LOG_ENABLED (default: false)
 *  - HTTP_LOG_ENDPOINT_URL
 *  - HTTP_LOG_BATCH_SIZE (default: 50)
 *  - HTTP_LOG_AUTH_TOKEN (optional)
 */
import { delay } from '../../common/index.js';
import { Env } from '../env.js';
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
import { HttpClient } from '../../tools/http/Http.js';
const isEnabled = () => Env.getBool('HTTP_LOG_ENABLED', false);
let buffer = [];
let flushPromise;
const postBatch = async (events) => {
    const endpoint = Env.get('HTTP_LOG_ENDPOINT_URL').trim();
    if (endpoint.length === 0) {
        throw ErrorFactory.createConfigError('HTTP_LOG_ENDPOINT_URL is required when HTTP logging is enabled');
    }
    const token = Env.get('HTTP_LOG_AUTH_TOKEN').trim();
    const builder = HttpClient.post(endpoint, {
        sentAt: new Date().toISOString(),
        count: events.length,
        events,
    });
    if (token.length > 0) {
        builder.withAuth(token, 'Bearer');
    }
    await builder.send();
};
const flushNow = async () => {
    const toSend = buffer;
    buffer = [];
    if (!isEnabled())
        return;
    if (toSend.length === 0)
        return;
    const maxRetries = 3;
    const attemptPost = async (attempt) => {
        try {
            await postBatch(toSend);
        }
        catch {
            if (attempt >= maxRetries)
                return;
            const backoffMs = 100 * 2 ** attempt;
            await delay(backoffMs);
            await attemptPost(attempt + 1);
        }
    };
    await attemptPost(0);
};
const scheduleFlush = async () => {
    if (flushPromise !== undefined)
        return flushPromise;
    const promise = new Promise((resolve) => {
        const run = async () => {
            try {
                await flushNow();
            }
            finally {
                resolve(undefined);
            }
        };
        if (typeof globalThis.setTimeout !== 'function') {
            void run();
            return;
        }
        globalThis.setTimeout(() => {
            void run();
        }, 0);
    });
    flushPromise = promise.finally(() => {
        flushPromise = undefined;
    });
    return flushPromise;
};
export const HttpLogger = Object.freeze({
    async enqueue(event) {
        if (!isEnabled())
            return Promise.resolve(); // NOSONAR
        buffer.push(event);
        const batchSize = Math.max(1, Env.getInt('HTTP_LOG_BATCH_SIZE', 50));
        if (buffer.length >= batchSize) {
            return scheduleFlush();
        }
        return scheduleFlush();
    },
});
export default HttpLogger;
