import { n as isTruthyEnvValue } from "./entry.js";
import { execFileSync } from "node:child_process";

//#region src/infra/shell-env.ts
const DEFAULT_TIMEOUT_MS = 15e3;
const DEFAULT_MAX_BUFFER_BYTES = 2 * 1024 * 1024;
let lastAppliedKeys = [];
let cachedShellPath;
function resolveTimeoutMs(timeoutMs) {
	if (typeof timeoutMs !== "number" || !Number.isFinite(timeoutMs)) return DEFAULT_TIMEOUT_MS;
	return Math.max(0, timeoutMs);
}
function resolveShell(env) {
	const shell = env.SHELL?.trim();
	return shell && shell.length > 0 ? shell : "/bin/sh";
}
function execLoginShellEnvZero(params) {
	return params.exec(params.shell, [
		"-l",
		"-c",
		"env -0"
	], {
		encoding: "buffer",
		timeout: params.timeoutMs,
		maxBuffer: DEFAULT_MAX_BUFFER_BYTES,
		env: params.env,
		stdio: [
			"ignore",
			"pipe",
			"pipe"
		]
	});
}
function parseShellEnv(stdout) {
	const shellEnv = /* @__PURE__ */ new Map();
	const parts = stdout.toString("utf8").split("\0");
	for (const part of parts) {
		if (!part) continue;
		const eq = part.indexOf("=");
		if (eq <= 0) continue;
		const key = part.slice(0, eq);
		const value = part.slice(eq + 1);
		if (!key) continue;
		shellEnv.set(key, value);
	}
	return shellEnv;
}
function loadShellEnvFallback(opts) {
	const logger = opts.logger ?? console;
	const exec = opts.exec ?? execFileSync;
	if (!opts.enabled) {
		lastAppliedKeys = [];
		return {
			ok: true,
			applied: [],
			skippedReason: "disabled"
		};
	}
	if (opts.expectedKeys.some((key) => Boolean(opts.env[key]?.trim()))) {
		lastAppliedKeys = [];
		return {
			ok: true,
			applied: [],
			skippedReason: "already-has-keys"
		};
	}
	const timeoutMs = resolveTimeoutMs(opts.timeoutMs);
	const shell = resolveShell(opts.env);
	let stdout;
	try {
		stdout = execLoginShellEnvZero({
			shell,
			env: opts.env,
			exec,
			timeoutMs
		});
	} catch (err) {
		const msg = err instanceof Error ? err.message : String(err);
		logger.warn(`[symi] shell env fallback failed: ${msg}`);
		lastAppliedKeys = [];
		return {
			ok: false,
			error: msg,
			applied: []
		};
	}
	const shellEnv = parseShellEnv(stdout);
	const applied = [];
	for (const key of opts.expectedKeys) {
		if (opts.env[key]?.trim()) continue;
		const value = shellEnv.get(key);
		if (!value?.trim()) continue;
		opts.env[key] = value;
		applied.push(key);
	}
	lastAppliedKeys = applied;
	return {
		ok: true,
		applied
	};
}
function shouldEnableShellEnvFallback(env) {
	return isTruthyEnvValue(env.SYMI_LOAD_SHELL_ENV);
}
function shouldDeferShellEnvFallback(env) {
	return isTruthyEnvValue(env.SYMI_DEFER_SHELL_ENV_FALLBACK);
}
function resolveShellEnvFallbackTimeoutMs(env) {
	const raw = env.SYMI_SHELL_ENV_TIMEOUT_MS?.trim();
	if (!raw) return DEFAULT_TIMEOUT_MS;
	const parsed = Number.parseInt(raw, 10);
	if (!Number.isFinite(parsed)) return DEFAULT_TIMEOUT_MS;
	return Math.max(0, parsed);
}
function getShellPathFromLoginShell(opts) {
	if (cachedShellPath !== void 0) return cachedShellPath;
	if ((opts.platform ?? process.platform) === "win32") {
		cachedShellPath = null;
		return cachedShellPath;
	}
	const exec = opts.exec ?? execFileSync;
	const timeoutMs = resolveTimeoutMs(opts.timeoutMs);
	const shell = resolveShell(opts.env);
	let stdout;
	try {
		stdout = execLoginShellEnvZero({
			shell,
			env: opts.env,
			exec,
			timeoutMs
		});
	} catch {
		cachedShellPath = null;
		return cachedShellPath;
	}
	const shellPath = parseShellEnv(stdout).get("PATH")?.trim();
	cachedShellPath = shellPath && shellPath.length > 0 ? shellPath : null;
	return cachedShellPath;
}
function getShellEnvAppliedKeys() {
	return [...lastAppliedKeys];
}

//#endregion
export { shouldDeferShellEnvFallback as a, resolveShellEnvFallbackTimeoutMs as i, getShellPathFromLoginShell as n, shouldEnableShellEnvFallback as o, loadShellEnvFallback as r, getShellEnvAppliedKeys as t };