-- El ritmo del latido llegaba a 300 s con el local sin movimiento, y la primera
-- venta del dia tardaba casi 5 minutos en sellarse. La 000121 art. 3 exige
-- transmision inmediata: el techo baja a 60 s.
CREATE OR REPLACE FUNCTION fiscal.latido(p_llave text, p_rif text, p_datos jsonb DEFAULT '{}'::jsonb)
 RETURNS jsonb
 LANGUAGE plpgsql
 SECURITY DEFINER
 SET search_path TO 'fiscal', 'public'
AS $function$
declare
  v_emisor uuid;
  v_serial text;
  v_pend int;
  v_anul int;
  v_ultima timestamptz;
  v_espera int;
begin
  v_emisor := fiscal.autenticar(p_llave, p_rif, 'estacion: latido');
  select serial into v_serial from fiscal.emisores where id = v_emisor;

  insert into fiscal.estaciones (emisor_id, nombre, version, equipo, ultimo_latido,
                                 pendientes, ultimo_documento, libro_integro)
    values (v_emisor,
            coalesce(nullif(p_datos->>'nombre', ''), 'Estacion Fiscal'),
            p_datos->>'version',
            coalesce(nullif(p_datos->>'equipo', ''), 'unico'),
            now(),
            coalesce((p_datos->>'pendientes')::int, 0),
            nullif(p_datos->>'ultimo_documento', '')::bigint,
            (p_datos->>'libro_integro')::boolean)
    on conflict (emisor_id, equipo) do update set
      nombre = excluded.nombre,
      version = excluded.version,
      ultimo_latido = now(),
      pendientes = excluded.pendientes,
      ultimo_documento = excluded.ultimo_documento,
      libro_integro = excluded.libro_integro;

  select count(*), max(creado_en) into v_pend, v_ultima
    from fiscal.cola_gustito
   where emisor_id = v_emisor and estado = 'pendiente'
     and proximo_intento_en <= now();

  select count(*) into v_anul
    from fiscal.anulaciones_gustito
   where emisor_id = v_emisor and estado = 'pendiente';

  -- El ritmo lo marca el movimiento del negocio, no el reloj.
  -- La transmision debe ser INMEDIATA (000121 art. 3 num. 2), asi que el techo
  -- es un minuto: antes llegaba a 300 s y la PRIMERA venta del dia se sellaba
  -- casi 5 minutos despues (medido en la prueba de estres: 290 s). El latido es
  -- barato y solo pide la lista pesada cuando de verdad hay algo.
  v_espera := case
    when v_pend > 0 or v_anul > 0 then 10                                -- hay trabajo: ya mismo
    when v_ultima > now() - interval '15 minutes' then 15                -- vendiendo: encima
    when v_ultima > now() - interval '2 hours' then 30                   -- venia vendiendo: atento
    else 60                                                              -- cerrado: igual mira cada minuto
  end;

  return jsonb_build_object(
    'ok', true,
    'pendientes_en_nube', v_pend,
    'anulaciones_en_nube', v_anul,
    'habilitado', true,
    'serial', v_serial,
    'volver_en_segundos', v_espera
  );
end;
$function$
;