import { AsyncLocalStorage } from "node:async_hooks";
import pino from "pino";
import pinoPretty from "pino-pretty";

//#region src/utils/logger.ts
/**
* Determines whether log output should be colorized.
*
* Checks in order:
* 1. NO_COLOR env var (standard: https://no-color.org/) - if set to any non-empty value, disables colors
* 2. Falls back to process.stdout.isTTY (colors enabled for interactive terminals)
*/
function shouldColorize() {
	if (process.env.NO_COLOR && process.env.NO_COLOR !== "") return false;
	return process.stdout.isTTY ?? false;
}
const loggerStorage = new AsyncLocalStorage();
function runWithLogContext(bindings, fn) {
	const child = (loggerStorage.getStore() ?? basePinoInstance).child(bindings);
	return loggerStorage.run(child, fn);
}
let basePinoInstance = pino({ level: "silent" });
function setBasePinoInstance(instance) {
	basePinoInstance = instance;
}
/**
* Pino logger implementation with transport customization support
*/
var PinoLogger = class PinoLogger {
	transportConfigs = [];
	pinoInstance;
	options;
	alsChildCache = /* @__PURE__ */ new WeakMap();
	isSnapshot;
	constructor(name, config = {}) {
		this.name = name;
		if (config.fromInstance) {
			this.pinoInstance = config.fromInstance;
			this.options = {};
			this.isSnapshot = config.snapshot ?? false;
			if (!this.isSnapshot) setBasePinoInstance(this.pinoInstance);
			return;
		}
		this.isSnapshot = false;
		this.options = {
			name: this.name,
			level: process.env.LOG_LEVEL || (process.env.ENVIRONMENT === "test" ? "silent" : "info"),
			serializers: {
				err: pino.stdSerializers.err,
				error: pino.stdSerializers.err,
				obj: (value) => ({ ...value })
			},
			redact: [
				"req.headers.authorization",
				"req.headers[\"x-inkeep-admin-authentication\"]",
				"req.headers.cookie",
				"req.headers[\"x-forwarded-cookie\"]"
			],
			...config.options
		};
		if (config.transportConfigs) this.transportConfigs = config.transportConfigs;
		if (this.transportConfigs.length > 0) this.pinoInstance = pino(this.options, pino.transport({ targets: this.transportConfigs }));
		else try {
			const prettyStream = pinoPretty({
				colorize: shouldColorize(),
				translateTime: "HH:MM:ss",
				ignore: "pid,hostname"
			});
			this.pinoInstance = pino(this.options, prettyStream);
		} catch (error) {
			console.warn("Warning: pino-pretty failed, using standard JSON output:", error);
			this.pinoInstance = pino(this.options);
		}
		setBasePinoInstance(this.pinoInstance);
	}
	/**
	* Recreate the pino instance with current transports
	*/
	recreateInstance() {
		if (this.pinoInstance && typeof this.pinoInstance.flush === "function") this.pinoInstance.flush();
		this.alsChildCache = /* @__PURE__ */ new WeakMap();
		if (this.transportConfigs.length === 0) try {
			const prettyStream = pinoPretty({
				colorize: shouldColorize(),
				translateTime: "HH:MM:ss",
				ignore: "pid,hostname"
			});
			this.pinoInstance = pino(this.options, prettyStream);
		} catch (error) {
			console.warn("Warning: pino-pretty failed, using standard JSON output:", error);
			this.pinoInstance = pino(this.options);
		}
		else {
			const multiTransport = { targets: this.transportConfigs };
			const pinoTransport = pino.transport(multiTransport);
			this.pinoInstance = pino(this.options, pinoTransport);
		}
	}
	/**
	* Add a new transport to the logger
	*/
	addTransport(transportConfig) {
		this.transportConfigs.push(transportConfig);
		this.recreateInstance();
	}
	/**
	* Remove a transport by index
	*/
	removeTransport(index) {
		if (index >= 0 && index < this.transportConfigs.length) {
			this.transportConfigs.splice(index, 1);
			this.recreateInstance();
		}
	}
	/**
	* Get current transports
	*/
	getTransports() {
		return [...this.transportConfigs];
	}
	/**
	* Update logger options
	*/
	updateOptions(options) {
		this.options = {
			...this.options,
			...options
		};
		this.recreateInstance();
	}
	/**
	* Get the underlying pino instance for advanced usage
	*/
	getPinoInstance() {
		return this.pinoInstance;
	}
	resolveInstance() {
		if (this.isSnapshot) return this.pinoInstance;
		const alsInstance = loggerStorage.getStore();
		if (!alsInstance) return this.pinoInstance;
		let cached = this.alsChildCache.get(alsInstance);
		if (!cached) {
			cached = alsInstance.child({ module: this.name });
			this.alsChildCache.set(alsInstance, cached);
		}
		return cached;
	}
	/**
	* Creates a new PinoLogger with the given bindings baked in (snapshot semantics).
	* Captures the current ALS context at call time. The returned logger does NOT
	* pick up subsequent ALS context changes — use for class member loggers that
	* are constructed once and reused within a request scope.
	*/
	with(bindings) {
		return new PinoLogger(this.name, {
			fromInstance: this.resolveInstance().child(bindings),
			snapshot: true
		});
	}
	child(bindings) {
		return this.with(bindings);
	}
	error(dataOrMessage, message) {
		if (message === void 0) this.resolveInstance().error(dataOrMessage);
		else this.resolveInstance().error(dataOrMessage, message);
	}
	warn(dataOrMessage, message) {
		if (message === void 0) this.resolveInstance().warn(dataOrMessage);
		else this.resolveInstance().warn(dataOrMessage, message);
	}
	info(dataOrMessage, message) {
		if (message === void 0) this.resolveInstance().info(dataOrMessage);
		else this.resolveInstance().info(dataOrMessage, message);
	}
	debug(dataOrMessage, message) {
		if (message === void 0) this.resolveInstance().debug(dataOrMessage);
		else this.resolveInstance().debug(dataOrMessage, message);
	}
};
/**
* Global logger factory singleton
*/
var LoggerFactory = class {
	config = {};
	loggers = /* @__PURE__ */ new Map();
	/**
	* Configure the logger factory
	*/
	configure(config) {
		this.config = config;
		this.loggers.clear();
	}
	/**
	* Get or create a logger instance
	*/
	getLogger(name) {
		if (this.loggers.has(name)) {
			const logger$1 = this.loggers.get(name);
			if (!logger$1) throw new Error(`Logger '${name}' not found in cache`);
			return logger$1;
		}
		let logger;
		if (this.config.loggerFactory) logger = this.config.loggerFactory(name);
		else if (this.config.defaultLogger) logger = this.config.defaultLogger;
		else logger = new PinoLogger(name, this.config.pinoConfig);
		this.loggers.set(name, logger);
		return logger;
	}
	/**
	* Reset factory to default state
	*/
	reset() {
		this.config = {};
		this.loggers.clear();
	}
};
const loggerFactory = new LoggerFactory();
/**
* Convenience function to get a logger
*/
function getLogger(name) {
	return loggerFactory.getLogger(name);
}

//#endregion
export { PinoLogger, getLogger, loggerFactory, runWithLogContext };