-- map register -> poslední známá hodnota na zařízení podle journalu.
-- Na rozdíl od fn_modbus_last_verified_map bere NEJNOVĚJŠÍ řádek per registr
-- a hodnotu vrací jen pokud je 'verified' NEBO 'written' (zápis potvrzený
-- TCP ackem, verify ještě nedoběhl / čtení zpět selhalo). Novější řádek
-- failed/mismatch/pending => registr v mapě chybí => exporter zapíše znovu
-- (po výpadku zařízení se konfigurace obnoví jedním zápisem).
-- Motivace: write-on-change pro EV wallboxy (EEPROM wear) — zápis se nesmí
-- opakovat každý export tick jen proto, že verify ještě neproběhl.

drop function if exists ems.fn_modbus_device_state_map;

create or replace function ems.fn_modbus_device_state_map(
  p_site_id int,
  p_asset_id int,
  p_asset_type text
)
returns jsonb
language sql
stable
as $fn$
  select coalesce(
    jsonb_object_agg(t.register::text, to_jsonb(t.val)),
    '{}'::jsonb
  )
  from (
    select distinct on (mc.register)
      mc.register,
      case
        when mc.status = 'verified' then mc.value_verified
        when mc.status = 'written' then coalesce(mc.value_written, mc.value_to_write)
        else null
      end as val
    from ems.modbus_command mc
    where mc.site_id = p_site_id
      and mc.asset_type = p_asset_type
      and mc.asset_id = p_asset_id
    order by mc.register, mc.id desc
  ) t
  where t.val is not null;
$fn$;

comment on function ems.fn_modbus_device_state_map is
  'Mapa register -> poslední známá hodnota na zařízení (nejnovější řádek modbus_command per registr; jen status written/verified, jinak registr chybí). Pro write-on-change drop v control exporteru (EV wallboxy) — šetří EEPROM, po výpadku (failed) se zapíše znovu.';
