-- ============================================================
-- Gustito Express — Candado de horario a nivel BD.
-- La app ya bloquea pedidos fuera de hora, pero esto lo blinda en la base:
-- ningun pedido entra si la tienda no esta abierta AHORA (switch manual +
-- horario configurado, en hora de Venezuela, soporta ventana que cruza
-- la medianoche). Misma logica que la tienda (estadoTienda en el front).
-- Se implementa como trigger BEFORE INSERT para no tocar crear_pedido().
-- ============================================================

create or replace function public.fn_tienda_abierta(p_rest uuid)
returns boolean
language plpgsql
stable
security definer
set search_path = public
as $$
declare
  r         record;
  h         jsonb;
  ve        timestamp := now() at time zone 'America/Caracas';
  dow       int := extract(dow from (now() at time zone 'America/Caracas'))::int; -- 0=dom..6=sab
  minutos   int := extract(hour from ve)::int * 60 + extract(minute from ve)::int;
  dias      text[] := array['dom','lun','mar','mie','jue','vie','sab'];
  keyhoy    text := dias[dow + 1];
  keyayer   text := dias[((dow + 6) % 7) + 1];
  choy      jsonb;
  cayer     jsonb;
  a         int;
  c         int;
  dentro    boolean := false;
begin
  select abierto, horarios into r from public.restaurantes where id = p_rest;
  if not found then return false; end if;
  if r.abierto is not true then return false; end if;         -- switch manual apagado
  h := r.horarios;
  if h is null then return true; end if;                       -- sin horario => rige el switch
  if not exists (select 1 from jsonb_each(h) e where (e.value->>'activo')::boolean is true) then
    return true;                                               -- horario vacio => rige el switch
  end if;

  choy  := h -> keyhoy;
  cayer := h -> keyayer;

  -- Ventana de hoy
  if choy is not null and (choy->>'activo')::boolean and choy->>'abre' is not null and choy->>'cierra' is not null then
    a := split_part(choy->>'abre', ':', 1)::int * 60 + split_part(choy->>'abre', ':', 2)::int;
    c := split_part(choy->>'cierra', ':', 1)::int * 60 + split_part(choy->>'cierra', ':', 2)::int;
    if c > a then
      if minutos >= a and minutos < c then dentro := true; end if;
    else                                                       -- cruza medianoche
      if minutos >= a then dentro := true; end if;
    end if;
  end if;

  -- Cola de la ventana de ayer que cruzo la medianoche
  if not dentro and cayer is not null and (cayer->>'activo')::boolean and cayer->>'abre' is not null and cayer->>'cierra' is not null then
    a := split_part(cayer->>'abre', ':', 1)::int * 60 + split_part(cayer->>'abre', ':', 2)::int;
    c := split_part(cayer->>'cierra', ':', 1)::int * 60 + split_part(cayer->>'cierra', ':', 2)::int;
    if c <= a and minutos < c then dentro := true; end if;
  end if;

  return dentro;
end;
$$;

create or replace function public.fn_pedido_horario_guard()
returns trigger
language plpgsql
security definer
set search_path = public
as $$
begin
  if not public.fn_tienda_abierta(new.restaurante_id) then
    raise exception 'El restaurante esta cerrado en este momento';
  end if;
  return new;
end;
$$;

drop trigger if exists trg_pedido_horario on public.pedidos;
create trigger trg_pedido_horario
  before insert on public.pedidos
  for each row execute function public.fn_pedido_horario_guard();
