/**
 * Resolve variable references (e.g. `@tenant_start_date`, `@Beginning_Of_Tax_Year`)
 * against the active form data and session-level constants.
 *
 * Variable syntax: `@<name>`. Resolution order:
 *   1. Session vars (by key name) — tax-year boundaries, client name, etc.
 *   2. Form-field values — looked up by `question_field_id` in `FbFormData.data[]`.
 *
 * Empty-string and whitespace-only values are treated as null so a chain like
 *   ['@tenant_start_date', '@Beginning_Of_Tax_Year']
 * falls through to the fallback when the user has not yet entered a tenant date.
 */
/** Resolve a single variable reference. Returns the value or null if unresolved/empty. */
export function resolve_variable(ref, ctx) {
    if (!ref.startsWith('@'))
        return null;
    const name = ref.slice(1);
    // Session-level constants take precedence by name (e.g. Beginning_Of_Tax_Year).
    if (Object.prototype.hasOwnProperty.call(ctx.session, name)) {
        return non_empty(ctx.session[name]);
    }
    // Otherwise, treat as form-field reference.
    if (ctx.form_data) {
        return non_empty(lookup_form_field(ctx.form_data, name));
    }
    return null;
}
/** Walk the chain. Return the first non-empty resolved value, or null if none resolve. */
export function resolve_variable_chain(chain, ctx) {
    for (const ref of chain) {
        const v = resolve_variable(ref, ctx);
        if (v !== null)
            return v;
    }
    return null;
}
function non_empty(v) {
    if (v === null || v === undefined)
        return null;
    const s = String(v).trim();
    return s.length === 0 ? null : s;
}
/**
 * Look up a form-field value by question id within FbFormData.
 *
 * The v2 hierarchical model stores user input under
 *   data[].client_data[].client_input.{data_text|data_option}
 * keyed against a question identified by `question.question_field_id`.
 *
 * We return the first non-empty `data_text` we find for the matching question;
 * if no text input exists we fall back to `data_option`. Returns null when the
 * question is absent or no input has been provided.
 */
function lookup_form_field(form_data, field_id) {
    for (const entry of form_data.data ?? []) {
        if (entry.question?.question_field_id !== field_id)
            continue;
        for (const cd of entry.client_data ?? []) {
            const inputs = Array.isArray(cd.client_input)
                ? cd.client_input
                : [cd.client_input];
            // Prefer text input; fall back to option code.
            for (const inp of inputs) {
                if (inp?.data_text != null && String(inp.data_text).trim().length > 0) {
                    return String(inp.data_text);
                }
            }
            for (const inp of inputs) {
                if (inp?.data_option != null && String(inp.data_option).trim().length > 0) {
                    return String(inp.data_option);
                }
            }
        }
    }
    return null;
}
//# sourceMappingURL=resolve_variable.js.map