"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.getThisNodeName = getThisNodeName;
exports.clearThisNodeName = clearThisNodeName;
exports.hostnameToUrl = hostnameToUrl;
exports.urlToNodeName = urlToNodeName;
exports.getThisNodeUrl = getThisNodeUrl;
const node_fs_1 = require("node:fs");
const node_crypto_1 = require("node:crypto");
const hdbTerms_ts_1 = require("../utility/hdbTerms.js");
const env = __importStar(require("../utility/environment/environmentManager.js"));
const logger_ts_1 = require("../utility/logging/logger.js");
const Server_ts_1 = require("./Server.js");
Object.defineProperty(Server_ts_1.server, 'hostname', {
    get() {
        return getThisNodeName();
    },
});
let commonNameFromCert;
function getCommonNameFromCert() {
    if (commonNameFromCert !== undefined)
        return commonNameFromCert;
    const certificatePath = env.get(hdbTerms_ts_1.CONFIG_PARAMS.OPERATIONSAPI_TLS_CERTIFICATE) || env.get(hdbTerms_ts_1.CONFIG_PARAMS.TLS_CERTIFICATE);
    if (certificatePath) {
        // we can use this to get the hostname if it isn't provided by config
        const certParsed = new node_crypto_1.X509Certificate((0, node_fs_1.readFileSync)(certificatePath));
        const subject = certParsed.subject;
        return (commonNameFromCert = subject?.match(/CN=(.*)/)?.[1] ?? null);
    }
}
let nodeName;
function getThisNodeName() {
    if (nodeName)
        return nodeName; // if already determined, just return
    nodeName = env.get(hdbTerms_ts_1.CONFIG_PARAMS.NODE_HOSTNAME); // standard config
    if (nodeName) {
        const replicationHostname = env.get('replication_hostname');
        if (replicationHostname && replicationHostname !== nodeName) {
            // If these are both set and differ, the node identity is ambiguous. node.hostname
            // wins (it is what this node identifies as), but if it doesn't match the name this
            // node is registered under in hdb_nodes, replication for that name silently turns
            // off (harper-pro#351). Do NOT blindly recommend cementing the already-picked
            // node.hostname value — that's how a wrong identity (e.g. 'localhost') gets locked
            // in. Steer the operator to reconcile against the registered node name instead.
            logger_ts_1.logger.warn?.(`The node.hostname (${nodeName}) and replication.hostname (${replicationHostname}) configuration values are both set and differ. This node will identify as "${nodeName}". Ensure that name matches this node's row in system.hdb_nodes; if it does not, set node.hostname (or remove it to fall back to replication.hostname) to match the registered node name, otherwise replication for this node will be disabled.`);
        }
        return nodeName;
    }
    // fallback to other means of getting the node name
    nodeName =
        env.get('replication_hostname') ?? // for backwards compatibility
            urlToNodeName(env.get('replication_url')) ??
            getCommonNameFromCert() ??
            getHostFromListeningPort('operationsapi_network_secureport') ??
            getHostFromListeningPort('operationsapi_network_port') ??
            '127.0.0.1';
    return nodeName;
}
function clearThisNodeName() {
    nodeName = undefined;
}
function getHostFromListeningPort(key) {
    const port = env.get(key);
    const lastColon = port?.lastIndexOf?.(':');
    if (lastColon > 0)
        return port.slice(0, lastColon);
}
function getPortFromListeningPort(key) {
    const port = env.get(key);
    const lastColon = port?.lastIndexOf?.(':');
    if (lastColon > 0)
        return +port.slice(lastColon + 1).replace(/[[\]]/g, '');
    return +port;
}
function hostnameToUrl(hostname) {
    if (!hostname)
        return undefined;
    let port = getPortFromListeningPort('replication_port');
    if (port)
        return `ws://${hostname}:${port}`;
    port = getPortFromListeningPort('replication_secureport');
    if (port)
        return `wss://${hostname}:${port}`;
    port = getPortFromListeningPort('operationsapi_network_port');
    if (port)
        return `ws://${hostname}:${port}`;
    port = getPortFromListeningPort('operationsapi_network_secureport');
    if (port)
        return `wss://${hostname}:${port}`;
}
function urlToNodeName(nodeUrl) {
    if (nodeUrl)
        return new URL(nodeUrl).hostname; // this the part of the URL that is the node name, as we want it to match common name in the certificate
}
function getThisNodeUrl() {
    const url = env.get(hdbTerms_ts_1.CONFIG_PARAMS.REPLICATION_URL);
    if (url)
        return url;
    return hostnameToUrl(getThisNodeName());
}
//# sourceMappingURL=nodeName.js.map