-- Persist first-class inference-round audit fields without changing RPC signatures.
-- Entropy, eliminated IDs and round_kind are extracted from inference_state.

begin;

alter table public.agentic_rectification_inference_transitions
  add column if not exists entropy_before double precision,
  add column if not exists entropy_after double precision,
  add column if not exists eliminated_candidate_ids jsonb not null default '[]'::jsonb,
  add column if not exists round_kind text;

alter table public.agentic_rectification_inference_transitions
  drop constraint if exists agentic_rectification_inference_round_kind_check;

alter table public.agentic_rectification_inference_transitions
  add constraint agentic_rectification_inference_round_kind_check
  check (round_kind is null or round_kind in ('informative', 'low_information'));

alter table public.agentic_rectification_inference_transitions
  drop constraint if exists agentic_rectification_inference_eliminated_ids_check;

alter table public.agentic_rectification_inference_transitions
  add constraint agentic_rectification_inference_eliminated_ids_check
  check (jsonb_typeof(eliminated_candidate_ids) = 'array');

create or replace function public.fill_agentic_rectification_inference_round()
returns trigger
language plpgsql
set search_path = ''
as $$
declare
  v_round jsonb;
  v_len integer;
begin
  v_round := case
    when jsonb_typeof(new.inference_state -> 'last_inference_round') = 'object'
      then new.inference_state -> 'last_inference_round'
    else null
  end;
  if v_round is null then
    v_len := jsonb_array_length(coalesce(new.inference_state -> 'rounds', '[]'::jsonb));
    if v_len > 0 then
      v_round := new.inference_state -> 'rounds' -> (v_len - 1);
    end if;
  end if;
  if v_round is not null and jsonb_typeof(v_round) = 'object' then
    begin
      new.entropy_before := (v_round ->> 'entropy_before')::double precision;
    exception when others then
      new.entropy_before := new.entropy_before;
    end;
    begin
      new.entropy_after := (v_round ->> 'entropy_after')::double precision;
    exception when others then
      new.entropy_after := new.entropy_after;
    end;
    if jsonb_typeof(v_round -> 'eliminated_ids') = 'array' then
      new.eliminated_candidate_ids := v_round -> 'eliminated_ids';
    end if;
    if v_round ->> 'kind' in ('informative', 'low_information') then
      new.round_kind := v_round ->> 'kind';
    end if;
  end if;
  if new.round_kind is null
    and new.posterior_before = new.posterior_after
    and new.score_deltas = '{}'::jsonb then
    new.round_kind := 'low_information';
  end if;
  return new;
end;
$$;

drop trigger if exists fill_agentic_rectification_inference_round
  on public.agentic_rectification_inference_transitions;

create trigger fill_agentic_rectification_inference_round
before insert or update of inference_state, posterior_before, posterior_after, score_deltas
on public.agentic_rectification_inference_transitions
for each row
execute function public.fill_agentic_rectification_inference_round();

create or replace function public.get_agentic_rectification_latest_inference_transition(
  p_user_id uuid,
  p_case_id uuid
)
returns jsonb
language plpgsql
stable
security definer
set search_path = ''
as $$
declare
  v_case public.agentic_rectification_cases%rowtype;
  v_transition public.agentic_rectification_inference_transitions%rowtype;
begin
  if p_user_id is null or p_case_id is null then
    raise exception 'agentic_rectification_invalid_input' using errcode = 'P0001';
  end if;
  select * into v_case
  from public.agentic_rectification_cases
  where id = p_case_id and user_id = p_user_id;
  if not found then
    raise exception 'agentic_rectification_case_not_found' using errcode = 'P0001';
  end if;
  select * into v_transition
  from public.agentic_rectification_inference_transitions
  where case_id = p_case_id
  order by revision desc
  limit 1;
  if not found then
    return null;
  end if;
  return jsonb_build_object(
    'id', v_transition.id,
    'result_id', v_transition.result_id,
    'previous_revision', v_transition.previous_revision,
    'revision', v_transition.revision,
    'probe_id', v_transition.probe_id,
    'reason', v_transition.reason,
    'decision_state_fingerprint', v_transition.decision_state_fingerprint,
    'inference_state', v_transition.inference_state,
    'posterior_before', v_transition.posterior_before,
    'posterior_after', v_transition.posterior_after,
    'score_deltas', v_transition.score_deltas,
    'entropy_before', v_transition.entropy_before,
    'entropy_after', v_transition.entropy_after,
    'eliminated_candidate_ids', v_transition.eliminated_candidate_ids,
    'round_kind', v_transition.round_kind
  );
end;
$$;

revoke all on function public.get_agentic_rectification_latest_inference_transition(uuid, uuid)
  from public, anon, authenticated;
grant execute on function public.get_agentic_rectification_latest_inference_transition(uuid, uuid)
  to service_role;

create or replace function public.list_agentic_rectification_inference_transitions(
  p_user_id uuid,
  p_case_id uuid
)
returns jsonb
language plpgsql
stable
security definer
set search_path = ''
as $$
declare
  v_case public.agentic_rectification_cases%rowtype;
  v_rows jsonb;
begin
  if p_user_id is null or p_case_id is null then
    raise exception 'agentic_rectification_invalid_input' using errcode = 'P0001';
  end if;
  select * into v_case
  from public.agentic_rectification_cases
  where id = p_case_id and user_id = p_user_id;
  if not found then
    raise exception 'agentic_rectification_case_not_found' using errcode = 'P0001';
  end if;
  select coalesce(jsonb_agg(jsonb_build_object(
    'id', item.id,
    'result_id', item.result_id,
    'previous_revision', item.previous_revision,
    'revision', item.revision,
    'probe_id', item.probe_id,
    'semantic_key', item.semantic_key,
    'candidate_split_hash', item.candidate_split_hash,
    'answer_class', item.answer_class,
    'reason', item.reason,
    'decision_state_fingerprint', item.decision_state_fingerprint,
    'inference_state', item.inference_state,
    'posterior_before', item.posterior_before,
    'posterior_after', item.posterior_after,
    'score_deltas', item.score_deltas,
    'entropy_before', item.entropy_before,
    'entropy_after', item.entropy_after,
    'eliminated_candidate_ids', item.eliminated_candidate_ids,
    'round_kind', item.round_kind
  ) order by item.revision), '[]'::jsonb)
  into v_rows
  from public.agentic_rectification_inference_transitions item
  where item.case_id = p_case_id;
  return v_rows;
end;
$$;

revoke all on function public.list_agentic_rectification_inference_transitions(uuid, uuid)
  from public, anon, authenticated;
grant execute on function public.list_agentic_rectification_inference_transitions(uuid, uuid)
  to service_role;

commit;
