-- =====================================================================
-- 0027_till_management.sql
--
-- Owner-facing till management:
--  - app.create_till(shop, name)              -> uuid
--  - app.rename_till(till, name)              -> void
--  - app.set_till_active(till, is_active)     -> void
--  - v_manage_tills view (owner sees all, including inactive)
-- =====================================================================

set search_path = app, public;

create or replace function app.create_till(
  p_shop uuid,
  p_name text
) returns uuid
language plpgsql
security definer
set search_path = app, public
as $$
declare
  v_id uuid;
  v_name text := nullif(btrim(p_name), '');
begin
  if v_name is null then raise exception 'till name is required'; end if;
  if not app.has_role_in_shop(p_shop, 'owner') then
    raise exception 'owner role required';
  end if;
  insert into app.tills(shop_id, name) values (p_shop, v_name)
    returning id into v_id;
  perform app.log_auth_event('till_created', p_shop, null,
    jsonb_build_object('till_id', v_id, 'name', v_name));
  return v_id;
exception
  when unique_violation then
    raise exception 'a till with this name already exists in the shop';
end;
$$;
revoke all on function app.create_till(uuid, text) from public;
grant execute on function app.create_till(uuid, text) to authenticated;

create or replace function app.rename_till(
  p_till uuid,
  p_name text
) returns void
language plpgsql
security definer
set search_path = app, public
as $$
declare
  v_shop uuid;
  v_name text := nullif(btrim(p_name), '');
begin
  if v_name is null then raise exception 'till name is required'; end if;
  select shop_id into v_shop from app.tills where id = p_till;
  if v_shop is null then raise exception 'till not found'; end if;
  if not app.has_role_in_shop(v_shop, 'owner') then
    raise exception 'owner role required';
  end if;
  update app.tills set name = v_name where id = p_till;
  perform app.log_auth_event('till_renamed', v_shop, null,
    jsonb_build_object('till_id', p_till, 'name', v_name));
exception
  when unique_violation then
    raise exception 'a till with this name already exists in the shop';
end;
$$;
revoke all on function app.rename_till(uuid, text) from public;
grant execute on function app.rename_till(uuid, text) to authenticated;

create or replace function app.set_till_active(
  p_till uuid,
  p_active boolean
) returns void
language plpgsql
security definer
set search_path = app, public
as $$
declare
  v_shop uuid;
begin
  select shop_id into v_shop from app.tills where id = p_till;
  if v_shop is null then raise exception 'till not found'; end if;
  if not app.has_role_in_shop(v_shop, 'owner') then
    raise exception 'owner role required';
  end if;
  -- Block deactivating a till that has an open shift on it.
  if p_active = false and exists (
    select 1 from app.shifts where till_id = p_till and status <> 'closed'
  ) then
    raise exception 'cannot deactivate a till with an open or pending shift';
  end if;
  update app.tills set is_active = coalesce(p_active, true) where id = p_till;
  perform app.log_auth_event(
    case when p_active then 'till_activated' else 'till_deactivated' end,
    v_shop, null, jsonb_build_object('till_id', p_till));
end;
$$;
revoke all on function app.set_till_active(uuid, boolean) from public;
grant execute on function app.set_till_active(uuid, boolean) to authenticated;

-- Owner view that also includes inactive tills, for the management UI.
drop view if exists app.v_manage_tills;
create view app.v_manage_tills as
  select t.id as till_id, t.shop_id, t.name, t.is_active, t.created_at
  from app.tills t
  where exists (
    select 1 from app.user_shop_assignments a
    where a.shop_id = t.shop_id
      and a.user_id = auth.uid()
      and a.role in ('owner', 'manager')
  );
grant select on app.v_manage_tills to authenticated;
