-- v12.2 strategic data-correctness delta.
-- Prior columns remain for compatibility; new code uses explicit security/lot weight semantics.

alter table signal_engine.sell_decision_context
    add column if not exists current_security_portfolio_weight numeric(12,8),
    add column if not exists current_lot_portfolio_weight numeric(12,8);

update signal_engine.sell_decision_context
set current_security_portfolio_weight = coalesce(current_security_portfolio_weight, current_portfolio_weight),
    current_lot_portfolio_weight = coalesce(current_lot_portfolio_weight, current_portfolio_weight)
where current_security_portfolio_weight is null
   or current_lot_portfolio_weight is null;

alter table signal_engine.sell_decision_context
    alter column current_security_portfolio_weight set not null,
    alter column current_lot_portfolio_weight set not null,
    drop constraint if exists ck_sell_context_security_weight,
    add constraint ck_sell_context_security_weight
        check (current_security_portfolio_weight between 0 and 1),
    drop constraint if exists ck_sell_context_lot_weight,
    add constraint ck_sell_context_lot_weight
        check (current_lot_portfolio_weight between 0 and current_security_portfolio_weight),
    drop constraint if exists ck_sell_context_published_cutoff,
    add constraint ck_sell_context_published_cutoff
        check (published_at_cutoff <= as_of);

comment on column signal_engine.sell_decision_context.current_portfolio_weight is
    'Legacy ambiguous field. Do not use in v12.2+ decisions.';
comment on column signal_engine.sell_decision_context.current_security_portfolio_weight is
    'Absolute portfolio weight of the security, 0..1.';
comment on column signal_engine.sell_decision_context.current_lot_portfolio_weight is
    'Absolute portfolio weight represented by the target PositionLot, 0..security weight.';

alter table signal_engine.signal_decision
    add column if not exists target_security_portfolio_weight_after numeric(12,8),
    add column if not exists policy_trace_json jsonb;

update signal_engine.signal_decision
set target_security_portfolio_weight_after = coalesce(
        target_security_portfolio_weight_after,
        target_portfolio_weight_after,
        0),
    policy_trace_json = coalesce(policy_trace_json, '[]'::jsonb)
where target_security_portfolio_weight_after is null
   or policy_trace_json is null;

alter table signal_engine.signal_decision
    alter column target_security_portfolio_weight_after set not null,
    alter column policy_trace_json set not null,
    drop constraint if exists ck_signal_decision_target_security_weight,
    add constraint ck_signal_decision_target_security_weight
        check (target_security_portfolio_weight_after between 0 and 1),
    drop constraint if exists ck_signal_decision_policy_trace_array,
    add constraint ck_signal_decision_policy_trace_array
        check (jsonb_typeof(policy_trace_json) = 'array');

comment on column signal_engine.signal_decision.target_portfolio_weight_after is
    'Legacy ambiguous target field. v12.2+ uses target_security_portfolio_weight_after.';

create index if not exists ix_signal_decision_policy_trace_gin
    on signal_engine.signal_decision using gin (policy_trace_json);
