function init_from_name_value_pairs(o, param_name, varargin)

% Initializes a dprior object for a single parameter from name-value pairs.
%
% INPUTS
% - o            [dprior]    object to initialize (handle, modified in place)
% - param_name   [char]      parameter name (e.g. 'stderr e', 'alpha')
% - varargin                 key-value pairs:
%     'shape'/'distribution'   distribution name or numeric code (mandatory)
%     'mean'/'p1'              prior mean
%     'std'/'p2'               prior standard deviation
%     'lower_bound'/'p3'       lower bound of support
%     'upper_bound'/'p4'       upper bound of support
%     'h1'                     first hyperparameter (alternative to mean/std)
%     'h2'                     second hyperparameter (alternative to mean/std)
%     'prior_trunc'            probability mass to exclude (default: 0)

% Copyright © 2026 Dynare Team
%
% This file is part of Dynare.
%
% Dynare is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare.  If not, see <https://www.gnu.org/licenses/>.

shape = [];
p1_val = NaN;
p2_val = NaN;
p3_val = NaN;
p4_val = NaN;
p6_val = NaN;
p7_val = NaN;
prior_trunc = 0;
has_moments = false;
has_hyperparams = false;

i = 1;
while i <= length(varargin)
    key = lower(char(varargin{i}));
    if i + 1 > length(varargin)
        error('dprior: key ''%s'' has no matching value.', varargin{i})
    end
    val = varargin{i+1};
    switch key
      case {'shape', 'distribution'}
        shape = parse_shape(val);
      case {'mean', 'p1'}
        p1_val = val;
        has_moments = true;
      case {'std', 'p2'}
        p2_val = val;
        has_moments = true;
      case {'lower_bound', 'p3'}
        p3_val = val;
      case {'upper_bound', 'p4'}
        p4_val = val;
      case 'h1'
        p6_val = val;
        has_hyperparams = true;
      case 'h2'
        p7_val = val;
        has_hyperparams = true;
      case 'prior_trunc'
        prior_trunc = val;
      otherwise
        error('dprior: unknown key ''%s''.', varargin{i})
    end
    i = i + 2;
end

if isempty(shape)
    error('dprior: ''shape'' (or ''distribution'') is mandatory.')
end

if has_moments && has_hyperparams
    error('dprior: specify either (mean, std) or (h1, h2), not both.')
end

if has_hyperparams
    if isnan(p6_val) || isnan(p7_val)
        error('dprior: both h1 and h2 must be provided when using hyperparameters directly.')
    end
    o.name = {param_name};
    o.p6 = p6_val;
    o.p7 = p7_val;
    o.p3 = p3_val;
    o.p4 = p4_val;
    set_defaults_and_backcompute(o, shape, prior_trunc);
    return
end

if ~has_moments
    if ~(shape == 5 && ~isnan(p3_val) && ~isnan(p4_val))
        error('dprior: either (mean, std) or (h1, h2) must be provided.')
    end
    % Uniform with bounds only: leave p1/p2 as NaN; uniform_specification
    % inside compute_hyperparameters will derive them from the bounds.
end

o.name = {param_name};
o.p1 = p1_val;
o.p2 = p2_val;
o.p3 = p3_val;
o.p4 = p4_val;

compute_hyperparameters(o, shape, prior_trunc);
