-- Notificaciones push al CLIENTE, ligadas a SU pedido.
-- El cliente pide sin cuenta, asi que la suscripcion del aparato se guarda en el
-- propio pedido (no en push_subs, que exige perfil_id).

-- 1) Suscripcion del aparato del cliente, guardada en su pedido.
alter table public.pedidos
  add column if not exists push_endpoint text,
  add column if not exists push_p256dh text,
  add column if not exists push_auth text;

-- 2) RPC para que el cliente (anon) guarde la suscripcion de SU aparato en su pedido.
--    Guard: solo pedidos recientes y no terminales (evita abuso).
create or replace function public.guardar_push_pedido(
  p_pedido_id uuid,
  p_endpoint text,
  p_p256dh text,
  p_auth text
) returns void
language plpgsql
security definer
set search_path to 'public'
as $$
begin
  update public.pedidos
     set push_endpoint = p_endpoint,
         push_p256dh   = p_p256dh,
         push_auth     = p_auth
   where id = p_pedido_id
     and recibido_en > now() - interval '12 hours'
     and estado not in ('entregado', 'cancelado');
end;
$$;

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

-- 3) Extender el trigger de push: ademas de negocio/repartidor, avisar al CLIENTE
--    segun el cambio de estado de su pedido. La parte de envio va en un bloque
--    exception para que un fallo de notificacion NUNCA rompa la operacion del pedido.
create or replace function public.tg_notificar_push()
returns trigger
language plpgsql
security definer
set search_path to 'public'
as $$
declare
  v_eventos text[] := '{}';
  v_evento text;
  v_secret text;
  v_url text := 'https://szzhhlevtrcambcoytiz.supabase.co/functions/v1/enviar-push';
  -- (la apikey se leia aqui escrita a mano; desde la migration
  --  20260719100000_push_anon_desde_vault.sql se lee de Vault)
  v_anon text := ''; begin
  if TG_OP = 'INSERT' then
    v_eventos := array_append(v_eventos, 'nuevo_pedido');
  elsif TG_OP = 'UPDATE' then
    -- Repartidores (logica existente)
    if new.tipo_entrega = 'delivery' and new.estado = 'listo' and new.repartidor_id is null
       and old.estado is distinct from 'listo' then
      v_eventos := array_append(v_eventos, 'listo_pool');
    end if;
    if new.repartidor_id is not null and old.repartidor_id is null and new.estado <> 'en_camino' then
      v_eventos := array_append(v_eventos, 'asignado');
    end if;
    -- Cliente (segun cambio de estado de SU pedido)
    if old.estado is distinct from new.estado then
      if new.estado = 'confirmado' then
        v_eventos := array_append(v_eventos, 'cliente_preparando');
      elsif new.estado = 'en_camino' then
        v_eventos := array_append(v_eventos, 'cliente_en_camino');
      elsif new.estado = 'listo' and new.tipo_entrega <> 'delivery' then
        v_eventos := array_append(v_eventos, 'cliente_listo');
      end if;
    end if;
  end if;

  if array_length(v_eventos, 1) is null then return null; end if;

  begin
    select decrypted_secret into v_secret from vault.decrypted_secrets where name = 'push_secret' limit 1;
    foreach v_evento in array v_eventos loop
      perform net.http_post(
        url := v_url,
        headers := jsonb_build_object(
          'Content-Type', 'application/json',
          'apikey', v_anon,
          'x-push-secret', coalesce(v_secret, '')
        ),
        body := jsonb_build_object('pedido_id', new.id, 'evento', v_evento)
      );
    end loop;
  exception when others then
    -- El push es best-effort: nunca dejar que rompa el insert/update del pedido.
    null;
  end;

  return null;
end;
$$;
