import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
function readInt(value, fallback, name) {
    if (value === undefined || value.trim() === '') {
        return fallback;
    }
    const parsed = Number(value);
    if (!Number.isInteger(parsed) || parsed <= 0) {
        throw new Error(`${name} must be a positive integer`);
    }
    return parsed;
}
function requireSecret(env, name, fallbackForTest) {
    const value = env[name]?.trim();
    const secret = value || (env.NODE_ENV === 'test' ? fallbackForTest : undefined);
    if (!secret) {
        throw new Error(`${name} is required`);
    }
    if (secret.length < 16) {
        throw new Error(`${name} must be at least 16 characters`);
    }
    if (name === 'NTERMINAL_SESSION_SECRET' && secret.length < 24) {
        throw new Error(`${name} must be at least 24 characters`);
    }
    return secret;
}
function parseTrustProxy(raw) {
    const value = raw?.trim();
    if (!value || value === 'false') {
        return false;
    }
    if (value === 'true') {
        return true;
    }
    // Number of hops or a comma-separated list of trusted IPs/CIDRs — passed through to Fastify.
    return value;
}
function resolveShell(env) {
    return env.NTERMINAL_SHELL?.trim() || env.SHELL?.trim() || (os.platform() === 'win32' ? 'powershell.exe' : '/bin/bash');
}
function parseRole(env) {
    const value = env.NTERMINAL_ROLE?.trim();
    if (value === 'main' || value === 'secondary') {
        return value;
    }
    if (env.NODE_ENV === 'test') {
        return 'main';
    }
    throw new Error('NTERMINAL_ROLE is required; run nterminal onboarding');
}
function parseOrigins(raw, host, port) {
    const configured = raw
        ?.split(',')
        .map((origin) => origin.trim())
        .filter(Boolean);
    if (configured && configured.length > 0) {
        return configured;
    }
    return [`http://${host}:${port}`, `http://localhost:${port}`, `http://127.0.0.1:${port}`];
}
export function loadDotEnvFile(filePath = '.env', baseEnv = process.env) {
    if (!fs.existsSync(filePath)) {
        return baseEnv;
    }
    const parsed = { ...baseEnv };
    const content = fs.readFileSync(filePath, 'utf8');
    for (const rawLine of content.split(/\r?\n/)) {
        const line = rawLine.trim();
        if (!line || line.startsWith('#')) {
            continue;
        }
        const separator = line.indexOf('=');
        if (separator === -1) {
            continue;
        }
        const key = line.slice(0, separator).trim();
        if (!key || parsed[key] !== undefined) {
            continue;
        }
        parsed[key] = stripEnvQuotes(line.slice(separator + 1).trim());
    }
    return parsed;
}
export function loadConfig(env = process.env) {
    const role = parseRole(env);
    const host = env.NTERMINAL_HOST?.trim() || '127.0.0.1';
    const port = readInt(env.NTERMINAL_PORT, 3107, 'NTERMINAL_PORT');
    // Default to the operator's HOME — process.cwd() was confusing because
    // nterminalctl deploy starts the server from the repo directory, so new
    // terminals opened in 127.0.0.1:3107 would start in the NTerminal repo
    // instead of the operator's working directory.
    const workspaceRoot = path.resolve(expandHomePath(env.NTERMINAL_WORKSPACE_ROOT?.trim() || os.homedir()));
    const statePath = path.resolve(env.NTERMINAL_STATE_PATH?.trim() || path.join(os.homedir(), '.nterminal/state.json'));
    const sessionTtlSeconds = readInt(env.NTERMINAL_SESSION_TTL_SECONDS, 43_200, 'NTERMINAL_SESSION_TTL_SECONDS');
    const uploadMaxFiles = readInt(env.NTERMINAL_UPLOAD_MAX_FILES, 1024, 'NTERMINAL_UPLOAD_MAX_FILES');
    const uploadMaxFileBytes = readInt(env.NTERMINAL_UPLOAD_MAX_FILE_BYTES, 536_870_912, 'NTERMINAL_UPLOAD_MAX_FILE_BYTES');
    const uploadMaxBatchBytes = readInt(env.NTERMINAL_UPLOAD_MAX_BATCH_BYTES, 2_147_483_648, 'NTERMINAL_UPLOAD_MAX_BATCH_BYTES');
    const fileListMaxEntries = readInt(env.NTERMINAL_FILE_LIST_MAX_ENTRIES, 2000, 'NTERMINAL_FILE_LIST_MAX_ENTRIES');
    const fileTextMaxBytes = readInt(env.NTERMINAL_FILE_TEXT_MAX_BYTES, 1_048_576, 'NTERMINAL_FILE_TEXT_MAX_BYTES');
    const filePreviewMaxBytes = readInt(env.NTERMINAL_FILE_PREVIEW_MAX_BYTES, 52_428_800, 'NTERMINAL_FILE_PREVIEW_MAX_BYTES');
    const isProduction = env.NODE_ENV === 'production';
    const rawAgentToken = env.NTERMINAL_AGENT_TOKEN?.trim() || null;
    const agentToken = rawAgentToken && rawAgentToken.length >= 32 ? rawAgentToken : null;
    const trustProxy = parseTrustProxy(env.NTERMINAL_TRUST_PROXY);
    return {
        role,
        host,
        port,
        workspaceRoot,
        shell: resolveShell(env),
        statePath,
        sessionSecret: requireSecret(env, 'NTERMINAL_SESSION_SECRET', 'test-session-secret-that-is-long-enough'),
        sessionTtlMs: sessionTtlSeconds * 1000,
        cookieSecure: env.NTERMINAL_COOKIE_SECURE === 'true' || (isProduction && env.NTERMINAL_COOKIE_SECURE !== 'false'),
        allowedOrigins: parseOrigins(env.NTERMINAL_ALLOWED_ORIGINS, host, port),
        staticRoot: path.resolve(env.NTERMINAL_STATIC_ROOT?.trim() || 'dist/client'),
        isProduction,
        agentToken,
        trustProxy,
        uploadMaxFiles,
        uploadMaxFileBytes,
        uploadMaxBatchBytes,
        fileListMaxEntries,
        fileTextMaxBytes,
        filePreviewMaxBytes
    };
}
export function isAllowedOrigin(config, origin) {
    return Boolean(origin && config.allowedOrigins.includes(origin));
}
function stripEnvQuotes(value) {
    if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
        return value.slice(1, -1);
    }
    return value;
}
function expandHomePath(value) {
    if (value === '~') {
        return os.homedir();
    }
    if (value.startsWith('~/')) {
        return path.join(os.homedir(), value.slice(2));
    }
    return value;
}
//# sourceMappingURL=config.js.map