create or replace function ems.fn_ev_session_transition(
  p_site_id int,
  p_charger_id int,
  p_prev_status text,
  p_new_status text,
  p_measured_at timestamptz
)
returns jsonb
language plpgsql
as $fn$
declare
  v_vehicle_id int;
begin
  if p_prev_status is not distinct from p_new_status then
    return jsonb_build_object('action', 'none');
  end if;

  if p_prev_status = 'available' and p_new_status is distinct from 'available' then
    select av.id
    into v_vehicle_id
    from ems.asset_vehicle av
    where av.site_id = p_site_id
      and av.default_charger_id = p_charger_id
      and av.active = true
    order by av.id
    limit 1;

    perform ems.fn_update_ev_arrival_stats(
      p_site_id,
      p_charger_id,
      v_vehicle_id,
      p_measured_at
    );

    insert into ems.ev_session (
      site_id,
      charger_id,
      vehicle_id,
      session_start,
      target_soc_pct,
      target_deadline
    )
    select
      ac.site_id,
      ac.id,
      av.id,
      now(),
      -- forecast z týdenního rytmu (ev_usage_stats), fallback defaulty;
      -- ruční přepis přes fn_ev_session_apply_patch vždy vyhrává.
      coalesce(fc.required_soc, av.default_target_soc_pct),
      coalesce(
        fc.expected_departure,
        case
          when av.default_deadline_hour is not null then
            (
              (timezone('Europe/Prague', now()))::date + interval '1 day'
              + make_interval(hours => av.default_deadline_hour)
            )::timestamp at time zone 'Europe/Prague'
        end
      )
    from ems.asset_ev_charger ac
    left join lateral (
      select v.id, v.default_target_soc_pct, v.default_deadline_hour,
             v.target_soc_forecast_enabled
      from ems.asset_vehicle v
      where v.default_charger_id = ac.id
        and v.site_id = ac.site_id
        and v.active = true
      order by v.id
      limit 1
    ) av on true
    left join lateral (
      select dep.expected_departure,
             ems.fn_ev_required_soc(av.id, dep.expected_departure) as required_soc
      from (
        select ems.fn_ev_next_departure(av.id, now()) as expected_departure
      ) dep
      where av.target_soc_forecast_enabled
        and dep.expected_departure is not null
    ) fc on true
    where ac.id = p_charger_id
      and ac.site_id = p_site_id
    on conflict (charger_id) where session_end is null do nothing;

    return jsonb_build_object('action', 'arrival');
  end if;

  if p_prev_status is distinct from 'available' and p_new_status = 'available' then
    update ems.ev_session es
    set session_end = now()
    where es.charger_id = p_charger_id
      and es.session_end is null;

    return jsonb_build_object('action', 'departure');
  end if;

  return jsonb_build_object('action', 'none');
end;
$fn$;

comment on function ems.fn_ev_session_transition(int, int, text, text, timestamptz) is
  'Detekce příjezdu/odjezdu EV po změně statusu nabíječky (telemetry_collector).';
