-- FIX: cuando el RESTAURANTE asigna un repartidor (asignar_repartidor), el pedido
-- quedaba 'listo' + asignado. La app del repartidor solo mostraba 'disponibles'
-- (listo + SIN asignar) y 'activas' (en_camino), asi que ese pedido quedaba INVISIBLE
-- y "no le llegaba nada". Ahora el repartidor ve sus pedidos asignados (listo) para poder salir.

-- 1) Entregas activas del repartidor: las que tiene asignadas y aun no entrega
--    (listo = se la asigno el restaurante y esta por salir; en_camino = ya va en ruta).
drop function if exists public.mis_entregas_activas();
create function public.mis_entregas_activas()
returns setof public.pedidos
language sql
stable
security definer
set search_path to 'public'
as $$
  select p.*
  from public.pedidos p
  join public.repartidores r on r.id = p.repartidor_id
  where r.perfil_id = auth.uid()
    and p.estado in ('listo', 'en_camino')
  order by p.en_camino_en asc nulls last, p.listo_en asc nulls last, p.recibido_en asc;
$$;
grant execute on function public.mis_entregas_activas() to authenticated;

-- 2) Al CANCELAR un pedido asignado, liberar al repartidor (antes solo se liberaba al ENTREGAR,
--    dejandolo 'ocupado' para siempre si el pedido se cancelaba). Mismo cuerpo + esa correccion.
create or replace function public.cambiar_estado_pedido(p_pedido_id uuid, p_nuevo_estado text)
returns text
language plpgsql
security definer
set search_path to 'public'
as $function$
declare
  v_ped           public.pedidos%rowtype;
  v_es_staff      boolean;
  v_es_repartidor boolean;
  v_permitidos    text[];
begin
  select * into v_ped from public.pedidos where id = p_pedido_id;
  if not found then raise exception 'Pedido no existe'; end if;

  v_es_staff := fn_es_staff_de(v_ped.restaurante_id) or fn_es_admin();
  v_es_repartidor := exists (
    select 1 from public.repartidores r
    where r.id = v_ped.repartidor_id and r.perfil_id = auth.uid()
  );
  if not (v_es_staff or v_es_repartidor) then
    raise exception 'Sin permiso para cambiar este pedido';
  end if;

  v_permitidos := case v_ped.estado
    when 'recibido'   then array['confirmado','cancelado']
    when 'confirmado' then array['preparando','cancelado']
    when 'preparando' then array['listo','cancelado']
    when 'listo'      then case when v_ped.tipo_entrega = 'delivery'
                                then array['en_camino','cancelado']
                                else array['entregado','cancelado'] end
    when 'en_camino'  then array['entregado']
    else array[]::text[]
  end;
  if not (p_nuevo_estado = any(v_permitidos)) then
    raise exception 'Transicion invalida: % -> %', v_ped.estado, p_nuevo_estado;
  end if;

  if v_es_repartidor and not v_es_staff and p_nuevo_estado not in ('en_camino','entregado') then
    raise exception 'El repartidor solo despacha y entrega';
  end if;

  update public.pedidos
     set estado        = p_nuevo_estado,
         confirmado_en = case when p_nuevo_estado='confirmado' then now() else confirmado_en end,
         listo_en      = case when p_nuevo_estado='listo'      then now() else listo_en end,
         en_camino_en  = case when p_nuevo_estado='en_camino'  then now() else en_camino_en end,
         entregado_en  = case when p_nuevo_estado='entregado'  then now() else entregado_en end,
         cancelado_en  = case when p_nuevo_estado='cancelado'  then now() else cancelado_en end
   where id = p_pedido_id;

  -- Liberar al repartidor tanto al ENTREGAR como al CANCELAR.
  if p_nuevo_estado in ('entregado','cancelado') and v_ped.repartidor_id is not null then
    update public.repartidores set estado='disponible' where id = v_ped.repartidor_id;
  end if;

  return p_nuevo_estado;
end;
$function$;

-- 3) Data fix: liberar repartidores que quedaron 'ocupado' sin ningun pedido activo asignado
--    (secuela del bug: cancelaciones previas los dejaron atascados).
update public.repartidores r
   set estado = 'disponible'
 where r.estado = 'ocupado'
   and not exists (
     select 1 from public.pedidos p
      where p.repartidor_id = r.id and p.estado in ('listo','en_camino')
   );
