-- LLEGA OTRO CLIENTE A UNA MESA QUE TODAVIA TIENE LA CUENTA DE OTRO
-- (2026-07-28, ultimo punto del sprint de mesas con Gilberto)
-- Hoy, al escanear el QR de una mesa que ya tiene pedidos, la tienda mete al
-- cliente DIRECTO en esa cuenta: ve lo que consumio el anterior y hasta puede
-- pagarlo. Bien si es un acompañante de la misma mesa (lo normal), muy malo si
-- es el cliente del turno siguiente y la mesa quedo mal cerrada.
-- No se puede adivinar cual de los dos es, asi que la tienda le PREGUNTA, y si
-- dice que acaba de llegar se le avisa al negocio (nadie libera plata sola).
begin;

-- 1. Tipo de llamada nuevo: "llegue y la mesa tiene una cuenta abierta".
alter table public.llamadas_mesa drop constraint if exists llamadas_mesa_tipo_check;
alter table public.llamadas_mesa
  add constraint llamadas_mesa_tipo_check check (tipo = any (array['mesero'::text, 'cuenta'::text, 'ocupada'::text]));

create or replace function public.llamar_mesero(p_cuenta_id uuid, p_tipo text default 'mesero'::text, p_nota text default null::text)
returns table(llamada_id uuid, ya_estaba boolean)
language plpgsql
security definer
set search_path to 'public'
as $fn$
declare
  v_rest uuid;
  v_mesa text;
  v_id   uuid;
begin
  -- 'ocupada': el cliente dice que llego a una mesa que todavia tiene cuenta.
  if p_tipo not in ('mesero','cuenta','ocupada') then raise exception 'Tipo de llamada invalido'; end if;
  select restaurante_id, mesa into v_rest, v_mesa
    from public.cuentas_mesa where id = p_cuenta_id and estado <> 'cerrada';
  if v_rest is null then raise exception 'La cuenta no esta disponible'; end if;

  insert into public.llamadas_mesa (cuenta_id, restaurante_id, mesa, tipo, nota)
    values (p_cuenta_id, v_rest, v_mesa, p_tipo, nullif(trim(coalesce(p_nota,'')), ''))
    on conflict (cuenta_id, tipo) where (atendida_en is null) do nothing
    returning id into v_id;

  if v_id is not null then
    return query select v_id, false;
  else
    select id into v_id from public.llamadas_mesa
      where cuenta_id = p_cuenta_id and tipo = p_tipo and atendida_en is null limit 1;
    return query select v_id, true;
  end if;
end;
$fn$;

grant execute on function public.llamar_mesero(uuid, text, text) to anon, authenticated, service_role;

-- 2. La tienda necesita saber DESDE CUANDO viene esa cuenta y de quien es, para
-- decidir si avisa suave ("se suma a la misma cuenta") o fuerte ("ojo, esto
-- lleva horas abierto"). Se dropea porque cambia el RETURNS TABLE.
drop function if exists public.cuenta_mesa_activa(uuid, text);

create or replace function public.cuenta_mesa_activa(p_restaurante_id uuid, p_mesa text)
returns table(
  id uuid,
  mesa text,
  estado text,
  total_usd numeric,
  mesero_nombre text,
  abierta_en timestamp with time zone,
  ultimo_pedido_en timestamp with time zone,
  abierta_por text
)
language sql
stable
security definer
set search_path to 'public'
as $fn$
  select c.id, c.mesa, c.estado,
         coalesce((select sum(p.total_usd) from public.pedidos p where p.cuenta_id = c.id and p.estado <> 'cancelado'), 0),
         c.mesero_nombre,
         c.abierta_en,
         (select max(p.recibido_en) from public.pedidos p where p.cuenta_id = c.id and p.estado <> 'cancelado'),
         coalesce(
           (select cm.nombre from public.comensales_mesa cm where cm.cuenta_id = c.id order by cm.orden limit 1),
           (select p.cliente_nombre from public.pedidos p where p.cuenta_id = c.id and p.estado <> 'cancelado' order by p.recibido_en limit 1)
         )
  from public.cuentas_mesa c
  where c.restaurante_id = p_restaurante_id
    and c.mesa = p_mesa
    and c.estado <> 'cerrada'
  limit 1;
$fn$;

grant execute on function public.cuenta_mesa_activa(uuid, text) to anon, authenticated, service_role;

commit;
