import path from "path";
import fs from "fs";
//#region src/core/logger.ts
const LEVELS = {
	debug: 10,
	info: 20,
	warn: 30,
	error: 40
};
function resolveDataDir(dataDir) {
	return dataDir ?? process.env["DXCRM_DATA_DIR"] ?? process.cwd();
}
function logsPath(dataDir) {
	return path.join(dataDir, ".agentic", "logs.ndjson");
}
function minLevel() {
	return LEVELS[(process.env["DXCRM_LOG_LEVEL"] ?? "info").toLowerCase()] ?? LEVELS.info;
}
/** Max bytes for the active ledger before it rotates (default 5 MB). */
function maxBytes() {
	const n = parseInt(process.env["DXCRM_LOG_MAX_BYTES"] ?? "", 10);
	return Number.isFinite(n) && n > 0 ? n : 5e6;
}
/** Number of rotated archives to keep (default 5; 0 = truncate, no archives). */
function maxFiles() {
	const n = parseInt(process.env["DXCRM_LOG_MAX_FILES"] ?? "", 10);
	return Number.isFinite(n) && n >= 0 ? n : 5;
}
/**
* Size-based log rotation. Before an append would push the active ledger past
* the byte budget, the archives shift (logs.ndjson.1 → .2 → … dropping the
* oldest) and the current ledger becomes logs.ndjson.1, leaving a fresh active
* file. Best-effort: any fs error here is swallowed so logging never breaks.
*/
function rotateIfNeeded(p, incomingBytes) {
	let size = 0;
	try {
		size = fs.statSync(p).size;
	} catch {
		return;
	}
	if (size + incomingBytes <= maxBytes()) return;
	const keep = maxFiles();
	try {
		if (keep <= 0) {
			fs.rmSync(p, { force: true });
			return;
		}
		fs.rmSync(`${p}.${keep}`, { force: true });
		for (let i = keep - 1; i >= 1; i--) if (fs.existsSync(`${p}.${i}`)) fs.renameSync(`${p}.${i}`, `${p}.${i + 1}`);
		fs.renameSync(p, `${p}.1`);
	} catch {}
}
/** Core log primitive. Honors DXCRM_LOG_LEVEL; mirrors to stderr unless off. */
function log(level, component, message, context, opts = {}) {
	if (LEVELS[level] < minLevel()) return;
	const entry = {
		ts: (/* @__PURE__ */ new Date()).toISOString(),
		level,
		component,
		message,
		...context && Object.keys(context).length > 0 ? { context } : {}
	};
	try {
		const p = logsPath(resolveDataDir(opts.dataDir));
		fs.mkdirSync(path.dirname(p), { recursive: true });
		const line = JSON.stringify(entry) + "\n";
		rotateIfNeeded(p, Buffer.byteLength(line));
		fs.appendFileSync(p, line, "utf-8");
	} catch {}
	if (process.env["DXCRM_LOG_STDERR"] !== "off") {
		const ctx = entry.context ? ` ${JSON.stringify(entry.context)}` : "";
		try {
			process.stderr.write(`[${component}] ${message}${ctx}\n`);
		} catch {}
	}
}
const logger = {
	debug: (component, message, context) => log("debug", component, message, context),
	info: (component, message, context) => log("info", component, message, context),
	warn: (component, message, context) => log("warn", component, message, context),
	error: (component, message, context) => log("error", component, message, context)
};
/** Read the active ledger plus rotated archives, oldest first. */
function readLedgerText(p) {
	const parts = [];
	for (let i = maxFiles(); i >= 1; i--) {
		const archive = `${p}.${i}`;
		if (fs.existsSync(archive)) try {
			parts.push(fs.readFileSync(archive, "utf-8"));
		} catch {}
	}
	if (fs.existsSync(p)) try {
		parts.push(fs.readFileSync(p, "utf-8"));
	} catch {}
	return parts.join("");
}
/** Read the log ledger (incl. rotated archives), skipping malformed lines, and filter. */
function queryLogs(dataDir, query = {}) {
	const entries = readLedgerText(logsPath(dataDir)).split("\n").filter(Boolean).flatMap((line) => {
		try {
			return [JSON.parse(line)];
		} catch {
			return [];
		}
	});
	const minRank = query.level ? LEVELS[query.level] : 0;
	const contains = query.contains?.toLowerCase();
	const filtered = entries.filter((e) => {
		if (LEVELS[e.level] < minRank) return false;
		if (query.component && e.component !== query.component) return false;
		if (query.since && e.ts < query.since) return false;
		if (contains && !e.message.toLowerCase().includes(contains)) return false;
		return true;
	});
	return query.limit && query.limit > 0 ? filtered.slice(-query.limit) : filtered;
}
/** Aggregate the (optionally filtered) log ledger for at-a-glance analysis. */
function summarizeLogs(dataDir, query = {}) {
	const entries = queryLogs(dataDir, query);
	const byLevel = {
		debug: 0,
		info: 0,
		warn: 0,
		error: 0
	};
	const byComponent = {};
	for (const e of entries) {
		byLevel[e.level] = (byLevel[e.level] ?? 0) + 1;
		byComponent[e.component] = (byComponent[e.component] ?? 0) + 1;
	}
	const summary = {
		total: entries.length,
		byLevel,
		byComponent,
		recentErrors: entries.filter((e) => e.level === "error").slice(-5)
	};
	if (entries.length > 0) {
		summary.firstTs = entries[0].ts;
		summary.lastTs = entries[entries.length - 1].ts;
	}
	return summary;
}
//#endregion
export { summarizeLogs as a, queryLogs as i, logger as n, logsPath as r, log as t };

//# sourceMappingURL=logger-Dyl4VcLO.js.map