export function resolveScope(schema, fileValues, env = {}) {
    const resolved = {};
    for (const key of Object.keys(schema)) {
        const field = schema[key];
        const envValue = resolveEnvValue(field, env, key);
        const fileValue = resolveFileValue(field, getOwnRecordValue(fileValues, key), key);
        const value = envValue ?? fileValue;
        defineDataProperty(resolved, key, (value === undefined ? cloneValue(field.default) : value));
    }
    return resolved;
}
function defineDataProperty(object, key, value) {
    Object.defineProperty(object, key, {
        configurable: true,
        enumerable: true,
        value,
        writable: true
    });
}
function getOwnRecordValue(record, key) {
    return record !== undefined && Object.prototype.hasOwnProperty.call(record, key)
        ? record[key]
        : undefined;
}
function cloneValue(value) {
    if (Array.isArray(value)) {
        return value.map((entry) => cloneValue(entry));
    }
    if (!value || typeof value !== "object") {
        return value;
    }
    const clone = Object.create(Object.getPrototypeOf(value));
    for (const [key, entry] of Object.entries(value)) {
        defineDataProperty(clone, key, cloneValue(entry));
    }
    return clone;
}
function resolveEnvValue(field, env, key) {
    if (!field.env) {
        return undefined;
    }
    const raw = getOwnRecordValue(env, field.env);
    if (raw === undefined) {
        return undefined;
    }
    return typeof raw === "string" ? coerceValue(field, raw, key) : undefined;
}
function resolveFileValue(field, value, key) {
    return coerceValue(field, value, key);
}
function coerceValue(field, value, key) {
    switch (field.type) {
        case "string":
            return typeof value === "string" ? value : undefined;
        case "number":
            return coerceNumber(value);
        case "boolean":
            return coerceBoolean(value);
        case "json":
            return coerceJson(field, value, key);
    }
}
function coerceNumber(value) {
    if (typeof value === "number" && Number.isFinite(value)) {
        return value;
    }
    if (typeof value !== "string" || value.trim().length === 0) {
        return undefined;
    }
    const parsed = Number(value);
    return Number.isFinite(parsed) ? parsed : undefined;
}
function coerceBoolean(value) {
    if (typeof value === "boolean") {
        return value;
    }
    if (value === "true" || value === "1") {
        return true;
    }
    if (value === "false" || value === "0") {
        return false;
    }
    return undefined;
}
function coerceJson(field, value, key) {
    if (value === undefined) {
        return undefined;
    }
    const parsedValue = parseJsonValue(value, key);
    try {
        return field.parse(parsedValue);
    }
    catch (error) {
        const message = error instanceof Error ? error.message : "Invalid JSON value.";
        throw new Error(`Invalid config value for "${key}": ${message}`);
    }
}
function parseJsonValue(value, key) {
    if (typeof value !== "string") {
        return value;
    }
    try {
        return JSON.parse(value);
    }
    catch {
        throw new Error(`Invalid config value for "${key}": expected valid JSON.`);
    }
}
