import { existsSync, readFileSync } from "fs";
import { dirname, join, resolve } from "path";
import { getHomeDir, normalizePath } from "./utils/paths.js";
import { isSplitLauncherRuntime, moduleFileFromMetaUrl } from "./utils/split-launcher.js";
// =============================================================================
// Package Detection
// =============================================================================
const __filename = moduleFileFromMetaUrl(import.meta.url, "app.js");
const __dirname = dirname(__filename);
/**
 * Detect if we're running as a Bun compiled binary.
 * Bun binaries have import.meta.url containing "$bunfs", "~BUN", or "%7EBUN" (Bun's virtual filesystem path).
 * Split Windows/macOS/Linux release launchers also set ATOMIC_CODING_AGENT before importing the sidecar app bundle.
 */
const bunFsMarkers = ["$bunfs", "~BUN", "%7EBUN"];
// Check process.argv[1] as well as import.meta.url: in a CJS (bytecode) bundle
// import.meta.url is rewritten to the original source path, but argv[1] still
// points into Bun's virtual filesystem.
export const isBunBinary = isSplitLauncherRuntime() ||
    [import.meta.url, process.argv[1] ?? ""].some((candidate) => bunFsMarkers.some((marker) => candidate.includes(marker)));
/**
 * Detect if we're running from a single-file bundle produced by `bun run bundle:dev`.
 * The bundle build inlines this env var via `--define`, so it is a compile-time
 * constant there and undefined everywhere else.
 */
export const isBundledBuild = process.env.ATOMIC_BUNDLED_BUILD === "1";
/** Detect if Bun is the runtime (compiled binary or bun run) */
export const isBunRuntime = !!process.versions.bun;
// =============================================================================
// Install Method Detection
// =============================================================================
import { detectInstallMethodForRuntime, getSelfUpdateCommandForRuntime, getSelfUpdateUnavailableInstructionForRuntime, getUpdateInstructionForRuntime, } from "./config-self-update.js";
function selfUpdateRuntime() {
    return {
        isBunBinary,
        isBunRuntime,
        moduleDir: __dirname,
        getPackageDir,
    };
}
export function detectInstallMethod() {
    return detectInstallMethodForRuntime(selfUpdateRuntime());
}
export function getSelfUpdateCommand(packageName, npmCommand, updatePackageName = packageName) {
    return getSelfUpdateCommandForRuntime(selfUpdateRuntime(), packageName, npmCommand, updatePackageName);
}
export function getSelfUpdateUnavailableInstruction(packageName, npmCommand, updatePackageName = packageName) {
    return getSelfUpdateUnavailableInstructionForRuntime(selfUpdateRuntime(), packageName, npmCommand, updatePackageName);
}
export function getUpdateInstruction(packageName) {
    return getUpdateInstructionForRuntime(selfUpdateRuntime(), packageName);
}
// =============================================================================
// Package Asset Paths (shipped with executable)
// =============================================================================
/**
 * Get the base directory for resolving package assets (themes, package.json, README.md, CHANGELOG.md).
 * - For Bun binary: returns the directory containing the executable
 * - For Node.js (dist/): returns __dirname (the dist/ directory)
 * - For tsx (src/): returns parent directory (the package root)
 */
export function getPackageDir() {
    // Allow override via environment variable (useful for Nix/Guix where store paths tokenize poorly).
    // This runs before package.json app config is read, so the env var name is hardcoded.
    const envDir = process.env.ATOMIC_PACKAGE_DIR ?? process.env.PI_PACKAGE_DIR;
    if (envDir) {
        return normalizePath(envDir);
    }
    if (isBunBinary) {
        // Bun binary: process.execPath points to the compiled executable
        return dirname(process.execPath);
    }
    // Node.js: walk up from __dirname until we find package.json
    let dir = __dirname;
    while (dir !== dirname(dir)) {
        if (existsSync(join(dir, "package.json"))) {
            return dir;
        }
        dir = dirname(dir);
    }
    // Fallback (shouldn't happen)
    return __dirname;
}
/**
 * Get path to built-in themes directory (shipped with package)
 * - For Bun binary: theme/ next to executable
 * - For Node.js (dist/): dist/modes/interactive/theme/
 * - For tsx (src/): src/modes/interactive/theme/
 */
export function getThemesDir() {
    if (isBunBinary) {
        return join(getPackageDir(), "theme");
    }
    // Theme is in modes/interactive/theme/ relative to src/ or dist/
    const packageDir = getPackageDir();
    const srcOrDist = existsSync(join(packageDir, "src")) ? "src" : "dist";
    return join(packageDir, srcOrDist, "modes", "interactive", "theme");
}
/**
 * Get path to HTML export template directory (shipped with package)
 * - For Bun binary: export-html/ next to executable
 * - For Node.js (dist/): dist/core/export-html/
 * - For tsx (src/): src/core/export-html/
 */
export function getExportTemplateDir() {
    if (isBunBinary) {
        return join(getPackageDir(), "export-html");
    }
    const packageDir = getPackageDir();
    const srcOrDist = existsSync(join(packageDir, "src")) ? "src" : "dist";
    return join(packageDir, srcOrDist, "core", "export-html");
}
/** Get path to package.json */
export function getPackageJsonPath() {
    return join(getPackageDir(), "package.json");
}
/** Get path to README.md */
export function getReadmePath() {
    return resolve(join(getPackageDir(), "README.md"));
}
/** Get path to docs directory */
export function getDocsPath() {
    return resolve(join(getPackageDir(), "docs"));
}
/** Get path to examples directory */
export function getExamplesPath() {
    return resolve(join(getPackageDir(), "examples"));
}
/** Get path to CHANGELOG.md */
export function getChangelogPath() {
    return resolve(join(getPackageDir(), "CHANGELOG.md"));
}
/**
 * Get path to built-in interactive assets directory.
 * - For Bun binary: assets/ next to executable
 * - For Node.js (dist/): dist/modes/interactive/assets/
 * - For tsx (src/): src/modes/interactive/assets/
 */
export function getInteractiveAssetsDir() {
    if (isBunBinary) {
        return join(getPackageDir(), "assets");
    }
    const packageDir = getPackageDir();
    const srcOrDist = existsSync(join(packageDir, "src")) ? "src" : "dist";
    return join(packageDir, srcOrDist, "modes", "interactive", "assets");
}
/** Get path to a bundled interactive asset */
export function getBundledInteractiveAssetPath(name) {
    return join(getInteractiveAssetsDir(), name);
}
let pkg = {};
try {
    pkg = JSON.parse(readFileSync(getPackageJsonPath(), "utf-8"));
}
catch (e) {
    const err = e;
    if (err.code !== "ENOENT")
        throw e;
}
function appNameFromPackageName(packageName) {
    const localName = packageName?.split("/").pop()?.trim();
    return localName && localName.length > 0 ? localName : undefined;
}
function readAppConfig(packageJson, appName) {
    if (appName) {
        const appConfig = packageJson[`${appName}Config`];
        if (appConfig && typeof appConfig === "object" && !Array.isArray(appConfig)) {
            return appConfig;
        }
    }
    return packageJson.piConfig;
}
export const PACKAGE_NAME = pkg.name || "@bastani/atomic";
const packageAppName = appNameFromPackageName(PACKAGE_NAME);
const appConfig = readAppConfig(pkg, packageAppName);
export const APP_NAME = appConfig?.name || packageAppName || "pi";
export const APP_TITLE = appConfig?.name !== undefined || APP_NAME !== "pi" ? APP_NAME : "π";
export const CONFIG_DIR_NAME = appConfig?.configDir || (APP_NAME === "pi" ? ".pi" : `.${APP_NAME}`);
export const LEGACY_CONFIG_DIR_NAME = ".pi";
export const CONFIG_DIR_NAMES = CONFIG_DIR_NAME === LEGACY_CONFIG_DIR_NAME ? [CONFIG_DIR_NAME] : [CONFIG_DIR_NAME, LEGACY_CONFIG_DIR_NAME];
export const VERSION = pkg.version || "0.0.0";
export const CHANGELOG_URL = appConfig?.changelogUrl?.trim() || undefined;
const ENV_PREFIX = APP_NAME.toUpperCase();
export const LEGACY_ENV_PREFIX = "PI";
// e.g., ATOMIC_CODING_AGENT_DIR (with PI_CODING_AGENT_DIR as a compatibility alias)
export const ENV_AGENT_DIR = `${ENV_PREFIX}_CODING_AGENT_DIR`;
export const ENV_SESSION_DIR = `${ENV_PREFIX}_CODING_AGENT_SESSION_DIR`;
export const ENV_PACKAGE_DIR = `${ENV_PREFIX}_PACKAGE_DIR`;
export const ENV_OFFLINE = `${ENV_PREFIX}_OFFLINE`;
export const ENV_SKIP_VERSION_CHECK = `${ENV_PREFIX}_SKIP_VERSION_CHECK`;
export const ENV_STARTUP_BENCHMARK = `${ENV_PREFIX}_STARTUP_BENCHMARK`;
export const ENV_TELEMETRY = `${ENV_PREFIX}_TELEMETRY`;
export const ENV_SHARE_VIEWER_URL = `${ENV_PREFIX}_SHARE_VIEWER_URL`;
export const ENV_CLEAR_ON_SHRINK = `${ENV_PREFIX}_CLEAR_ON_SHRINK`;
export const ENV_HARDWARE_CURSOR = `${ENV_PREFIX}_HARDWARE_CURSOR`;
export const ENV_TIMING = `${ENV_PREFIX}_TIMING`;
export const ENV_CODEX_FAST_MODE = `${ENV_PREFIX}_CODEX_FAST_MODE`;
export const WORKFLOW_STAGE_SUBAGENT_GUARD_ENV = `${ENV_PREFIX}_WORKFLOW_STAGE_SUBAGENT_GUARD`;
function parseCodexFastModeEnvBoolean(value) {
    switch (value?.trim().toLowerCase()) {
        case "1":
        case "true":
        case "enabled":
        case "on":
            return true;
        case "0":
        case "false":
        case "disabled":
        case "off":
            return false;
        default:
            return undefined;
    }
}
export function serializeCodexFastModeEnvironmentSettings(settings) {
    return `chat=${settings.chat ? "1" : "0"};workflow=${settings.workflow ? "1" : "0"}`;
}
export function parseCodexFastModeEnvironmentSettings(value) {
    if (!value)
        return undefined;
    const settings = {};
    for (const part of value.split(/[;,]/)) {
        const separatorIndex = part.indexOf("=");
        if (separatorIndex === -1)
            continue;
        const key = part.slice(0, separatorIndex).trim();
        const parsedValue = parseCodexFastModeEnvBoolean(part.slice(separatorIndex + 1));
        if (parsedValue === undefined)
            continue;
        if (key === "chat")
            settings.chat = parsedValue;
        if (key === "workflow")
            settings.workflow = parsedValue;
    }
    return settings.chat !== undefined || settings.workflow !== undefined ? settings : undefined;
}
export function getCodexFastModeEnvironmentSettings() {
    return parseCodexFastModeEnvironmentSettings(getEnvValue(ENV_CODEX_FAST_MODE));
}
export function setCodexFastModeEnvironmentSettings(settings) {
    setEnvValue(ENV_CODEX_FAST_MODE, serializeCodexFastModeEnvironmentSettings(settings));
}
export function getEnvNames(name) {
    if (ENV_PREFIX === LEGACY_ENV_PREFIX || !name.startsWith(`${ENV_PREFIX}_`))
        return [name];
    return [name, `${LEGACY_ENV_PREFIX}_${name.slice(ENV_PREFIX.length + 1)}`];
}
export function getEnvValue(name) {
    for (const candidate of getEnvNames(name)) {
        const value = process.env[candidate];
        if (value !== undefined)
            return value;
    }
    return undefined;
}
export function hasEnvValue(name) {
    return getEnvValue(name) !== undefined;
}
export function setEnvValue(name, value) {
    process.env[name] = value;
}
export function expandTildePath(path) {
    return normalizePath(path);
}
const DEFAULT_SHARE_VIEWER_URL = "https://pi.dev/session/";
/** Get the share viewer URL for a gist ID */
export function getShareViewerUrl(gistId) {
    const baseUrl = getEnvValue(ENV_SHARE_VIEWER_URL) || DEFAULT_SHARE_VIEWER_URL;
    return `${baseUrl}#${gistId}`;
}
// =============================================================================
// User Config Paths (~/.atomic/agent/*)
// =============================================================================
/** Get the agent config directory (e.g., ~/.atomic/agent/) */
export function getAgentDir() {
    const envDir = getEnvValue(ENV_AGENT_DIR);
    if (envDir) {
        return expandTildePath(envDir);
    }
    return join(getHomeDir(), CONFIG_DIR_NAME, "agent");
}
/** Get the legacy pi agent config directory (e.g., ~/.pi/agent/) */
export function getLegacyAgentDir() {
    return join(getHomeDir(), LEGACY_CONFIG_DIR_NAME, "agent");
}
/** Get agent config directories in precedence order (primary first, then legacy). */
export function getAgentDirs() {
    const primary = getAgentDir();
    if (hasEnvValue(ENV_AGENT_DIR) || CONFIG_DIR_NAME === LEGACY_CONFIG_DIR_NAME) {
        return [primary];
    }
    const legacy = getLegacyAgentDir();
    return legacy === primary ? [primary] : [primary, legacy];
}
/** Get user config root directories in precedence order (primary first, then legacy). */
export function getUserConfigDirs() {
    return CONFIG_DIR_NAMES.map((name) => join(getHomeDir(), name));
}
/** Get project config directories in precedence order (primary first, then legacy). */
export function getProjectConfigDirs(cwd) {
    return CONFIG_DIR_NAMES.map((name) => join(cwd, name));
}
/** Get a path inside every user config root directory. */
export function getUserConfigPaths(...segments) {
    return getUserConfigDirs().map((dir) => join(dir, ...segments));
}
/** Get a path inside every agent config directory. */
export function getAgentConfigPaths(...segments) {
    return getAgentDirs().map((dir) => join(dir, ...segments));
}
/** Get a path inside every project config directory. */
export function getProjectConfigPaths(cwd, ...segments) {
    return getProjectConfigDirs(cwd).map((dir) => join(dir, ...segments));
}
/** Get path to user's custom themes directory */
export function getCustomThemesDir() {
    return join(getAgentDir(), "themes");
}
/** Get path to models.json */
export function getModelsPath() {
    return join(getAgentDir(), "models.json");
}
/** Get path to auth.json */
export function getAuthPath() {
    return join(getAgentDir(), "auth.json");
}
/** Get path to settings.json */
export function getSettingsPath() {
    return join(getAgentDir(), "settings.json");
}
/** Get path to tools directory */
export function getToolsDir() {
    return join(getAgentDir(), "tools");
}
/** Get path to managed binaries directory (fd, rg) */
export function getBinDir() {
    return join(getAgentDir(), "bin");
}
/**
 * Get path to the extension transpile cache directory (jiti fsCache).
 * Scoped by version so release upgrades never read stale transpiled output.
 */
export function getExtensionTranspileCacheDir() {
    return join(getAgentDir(), "cache", "jiti", VERSION);
}
/** Get path to prompt templates directory */
export function getPromptsDir() {
    return join(getAgentDir(), "prompts");
}
/** Get path to sessions directory */
export function getSessionsDir() {
    return join(getAgentDir(), "sessions");
}
/** Get path to debug log file */
export function getDebugLogPath() {
    return join(getAgentDir(), `${APP_NAME}-debug.log`);
}
//# sourceMappingURL=config.js.map