-- Expose per-tool started_at / elapsed_ms / failure reason on turn receipts.
-- Timing is derived from the started row vs the terminal row; no new columns.

begin;

create or replace function public.get_agentic_rectification_turn_receipt(
  p_user_id uuid,
  p_case_id uuid,
  p_turn_id uuid
)
returns jsonb
language plpgsql
security definer
set search_path = ''
as $$
declare
  v_turn public.agentic_rectification_turns%rowtype;
  v_case public.agentic_rectification_cases%rowtype;
  v_attempt_id uuid;
  v_phases jsonb;
  v_tool_activities jsonb;
  v_tools jsonb;
  v_methods jsonb;
  v_engine_version text;
begin
  if p_user_id is null or p_case_id is null or p_turn_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_turn
  from public.agentic_rectification_turns
  where id = p_turn_id and case_id = p_case_id;
  if not found then
    raise exception 'agentic_rectification_turn_not_found' using errcode = 'P0001';
  end if;

  v_attempt_id := v_turn.successful_attempt_id;
  if v_attempt_id is null then
    select id into v_attempt_id
    from public.agentic_rectification_run_attempts
    where turn_id = p_turn_id
    order by attempt_number desc
    limit 1;
  end if;

  select coalesce(jsonb_agg(
    jsonb_build_object('phase', rp.phase, 'tool', rp.tool_name)
    order by rp.sequence, rp.created_at, rp.id
  ), '[]'::jsonb) into v_phases
  from public.agentic_rectification_run_phases rp
  where rp.turn_id = p_turn_id
    and (
      (v_attempt_id is not null and rp.attempt_id = v_attempt_id)
      or (v_attempt_id is null and rp.attempt_id is null)
    );

  with latest_terminal as materialized (
    select distinct on (tr.tool_name)
      tr.id,
      tr.tool_name,
      tr.status,
      tr.executed_methods,
      tr.started_at,
      tr.safe_error_code,
      tr.result_fingerprint
    from public.agentic_rectification_tool_receipts tr
    where tr.turn_id = p_turn_id
      and tr.status in ('completed', 'failed')
      and (
        (v_attempt_id is not null and tr.attempt_id = v_attempt_id)
        or (v_attempt_id is null and tr.attempt_id is null)
      )
    order by tr.tool_name, tr.started_at desc, tr.id desc
  ),
  latest_started as materialized (
    select distinct on (tr.tool_name)
      tr.tool_name,
      tr.started_at
    from public.agentic_rectification_tool_receipts tr
    where tr.turn_id = p_turn_id
      and tr.status = 'started'
      and (
        (v_attempt_id is not null and tr.attempt_id = v_attempt_id)
        or (v_attempt_id is null and tr.attempt_id is null)
      )
    order by tr.tool_name, tr.started_at desc, tr.id desc
  )
  select
    coalesce(jsonb_agg(
      jsonb_strip_nulls(jsonb_build_object(
        'tool', terminal.tool_name,
        'status', terminal.status,
        'methods', case
          when terminal.status = 'completed' then terminal.executed_methods
          else '[]'::jsonb
        end,
        'started_at', coalesce(started.started_at, terminal.started_at),
        'elapsed_ms', greatest(
          0,
          (extract(epoch from (
            terminal.started_at - coalesce(started.started_at, terminal.started_at)
          )) * 1000)::int
        ),
        'error', terminal.safe_error_code,
        'result_fingerprint', terminal.result_fingerprint
      )) order by coalesce(started.started_at, terminal.started_at), terminal.id
    ), '[]'::jsonb),
    coalesce(jsonb_agg(terminal.tool_name order by coalesce(started.started_at, terminal.started_at), terminal.id)
      filter (where terminal.status = 'completed'), '[]'::jsonb)
  into v_tool_activities, v_tools
  from latest_terminal terminal
  left join latest_started started on started.tool_name = terminal.tool_name;

  with latest_terminal as materialized (
    select distinct on (tr.tool_name)
      tr.tool_name,
      tr.status,
      tr.executed_methods
    from public.agentic_rectification_tool_receipts tr
    where tr.turn_id = p_turn_id
      and tr.status in ('completed', 'failed')
      and (
        (v_attempt_id is not null and tr.attempt_id = v_attempt_id)
        or (v_attempt_id is null and tr.attempt_id is null)
      )
    order by tr.tool_name, tr.started_at desc, tr.id desc
  )
  select coalesce(jsonb_agg(method order by method), '[]'::jsonb) into v_methods
  from (
    select distinct jsonb_array_elements_text(terminal.executed_methods) as method
    from latest_terminal terminal
    where terminal.status = 'completed'
  ) methods;

  select max(tr.engine_version) into v_engine_version
  from public.agentic_rectification_tool_receipts tr
  where tr.turn_id = p_turn_id and tr.engine_version is not null
    and (
      (v_attempt_id is not null and tr.attempt_id = v_attempt_id)
      or (v_attempt_id is null and tr.attempt_id is null)
    );

  return jsonb_build_object(
    'turn_id', v_turn.id,
    'attempt_id', v_attempt_id,
    'status', v_turn.status,
    'skill_name', v_case.skill_name,
    'skill_version', v_case.skill_version,
    'engine_version', v_engine_version,
    'phases', v_phases,
    'tool_activities', v_tool_activities,
    'tools', v_tools,
    'methods', v_methods,
    'started_at', v_turn.created_at,
    'completed_at', v_turn.completed_at
  );
end;
$$;

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

commit;
