-- =====================================================================
-- Migration 0038 — Shop-scoped service titles and icons.
--
-- Lets owners/managers customize how transaction services appear in the
-- UI without changing canonical service codes used by accounting logic.
-- =====================================================================

set search_path = app, public;

create table if not exists app.service_ui_settings (
  shop_id       uuid not null references app.shops(id) on delete cascade,
  service_code  text not null references app.services(code) on delete cascade,
  display_name  text,
  icon          text,
  updated_at    timestamptz not null default now(),
  updated_by    uuid references auth.users(id),
  primary key (shop_id, service_code),
  constraint service_ui_display_name_len check (display_name is null or length(display_name) between 1 and 80),
  constraint service_ui_icon_len check (icon is null or length(icon) between 1 and 16)
);

alter table app.service_ui_settings enable row level security;
alter table app.service_ui_settings force row level security;
revoke insert, update, delete on app.service_ui_settings from authenticated;
grant select on app.service_ui_settings to authenticated;

drop policy if exists service_ui_select on app.service_ui_settings;
create policy service_ui_select on app.service_ui_settings
for select using (
  app.has_any_role_in_shop(shop_id, array['owner','manager','cashier','auditor']::app.business_role[])
);

create or replace view app.v_service_ui_settings as
select
  s.id as shop_id,
  svc.code as service_code,
  svc.name as default_name,
  svc.category,
  svc.is_active,
  ui.display_name,
  ui.icon,
  ui.updated_at,
  ui.updated_by
from app.shops s
join app.services svc on svc.is_active = true
left join app.service_ui_settings ui
  on ui.shop_id = s.id and ui.service_code = svc.code
where app.has_any_role_in_shop(s.id, array['owner','manager','cashier','auditor']::app.business_role[]);

grant select on app.v_service_ui_settings to authenticated;

create or replace function app.set_service_ui_setting(
  p_shop uuid,
  p_service_code text,
  p_display_name text,
  p_icon text
) returns void
language plpgsql
security definer
set search_path = app, public
as $$
declare
  v_display text := nullif(btrim(coalesce(p_display_name, '')), '');
  v_icon text := nullif(btrim(coalesce(p_icon, '')), '');
begin
  if not app.has_any_role_in_shop(p_shop, array['owner','manager']::app.business_role[]) then
    raise exception 'manager or owner role required';
  end if;
  if not exists (select 1 from app.services where code = p_service_code and is_active) then
    raise exception 'unknown or inactive service %', p_service_code;
  end if;
  if v_display is null and v_icon is null then
    delete from app.service_ui_settings
    where shop_id = p_shop and service_code = p_service_code;
    return;
  end if;

  insert into app.service_ui_settings(shop_id, service_code, display_name, icon, updated_by)
  values (p_shop, p_service_code, v_display, v_icon, auth.uid())
  on conflict (shop_id, service_code) do update
    set display_name = excluded.display_name,
        icon = excluded.icon,
        updated_at = now(),
        updated_by = auth.uid();
end;
$$;

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

-- Recent transaction rows should use the shop's display title when set.
drop view if exists app.v_my_recent_transactions;
create view app.v_my_recent_transactions as
  select t.id, t.reference_no, t.shop_id, t.till_id, t.shift_id,
         t.service_code,
         coalesce(ui.display_name, s.name) as service_name,
         s.category,
         t.payment_method,
         t.gross_usd, t.gross_lbp,
         t.fee_usd + t.commission_usd as revenue_usd,
         t.fee_lbp + t.commission_lbp as revenue_lbp,
         t.external_ref, t.external_ref_provider,
         t.beneficiary_name, t.beneficiary_phone,
         t.status, t.occurred_at, t.user_id
  from app.transactions t
  join app.services s on s.code = t.service_code
  left join app.service_ui_settings ui
    on ui.shop_id = t.shop_id and ui.service_code = t.service_code
  where t.user_id = auth.uid()
     or app.has_any_role_in_shop(t.shop_id,
          array['owner','manager','auditor']::app.business_role[]);

grant select on app.v_my_recent_transactions to authenticated;
