-- =========================================================
-- TABLERO CDC - Acceso autorizado por Supabase
-- Ejecutar en Supabase SQL Editor ANTES de desplegar el ZIP.
--
-- Objetivo:
-- - El acceso a la app ya no depende de una lista fija en código.
-- - Los usuarios permitidos viven en public.tablero_cdc_allowed_users.
-- - Para agregar/quitar acceso luego, se actualiza esta tabla en Supabase.
-- - También centraliza permisos especiales usados por la app:
--   * can_manage_internal_pricing
--   * can_delete_projects
--   * can_control_pricing_summary
-- =========================================================

begin;

create table if not exists public.tablero_cdc_allowed_users (
  email text primary key,
  full_name text,
  role text not null default 'user',
  is_active boolean not null default true,
  can_delete_projects boolean not null default false,
  can_manage_internal_pricing boolean not null default false,
  can_control_pricing_summary boolean not null default false,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now()
);

comment on table public.tablero_cdc_allowed_users is
  'Lista central de usuarios autorizados para entrar al Tablero CDC.';

comment on column public.tablero_cdc_allowed_users.role is
  'Rol lógico de la app. director_creativo habilita comportamiento especial de Director Creativo.';

create or replace function public.set_tablero_cdc_allowed_users_updated_at()
returns trigger
language plpgsql
as $$
begin
  new.email = lower(trim(new.email));
  new.updated_at = now();
  return new;
end;
$$;

drop trigger if exists trg_tablero_cdc_allowed_users_updated_at on public.tablero_cdc_allowed_users;

create trigger trg_tablero_cdc_allowed_users_updated_at
before insert or update on public.tablero_cdc_allowed_users
for each row
execute function public.set_tablero_cdc_allowed_users_updated_at();

-- Usuarios autorizados iniciales.
-- Nota: Re-ejecutar este SQL mantiene estos usuarios activos y actualiza sus permisos base.
insert into public.tablero_cdc_allowed_users (
  email,
  full_name,
  role,
  is_active,
  can_delete_projects,
  can_manage_internal_pricing,
  can_control_pricing_summary
)
values
  (
    'iaracena@gomezleemarketing.com',
    'Isaac Daniel Aracena Toribio',
    'admin_it',
    true,
    true,
    true,
    true
  ),
  (
    'jgomez@gomezleemarketing.com',
    'José Leopoldo Gomez',
    'leadership',
    true,
    false,
    false,
    true
  ),
  (
    'gmarrero@gomezleemarketing.com',
    'Gerardo Marrero',
    'director_creativo',
    true,
    true,
    true,
    true
  ),
  (
    'areyes@gomezleemarketing.com',
    'Alicia Thaía Reyes',
    'user',
    true,
    true,
    true,
    false
  ),
  (
    'boliva@gomezleemarketing.com',
    'Bonnie Oliva',
    'user',
    true,
    false,
    false,
    false
  ),
  (
    'obrisceno@gomezleemarketing.com',
    'Oscar Brisceño',
    'user',
    true,
    false,
    false,
    false
  ),
  (
    'lavila01@gomezlee.marketing',
    'Lady Avila Faura',
    'user',
    true,
    false,
    false,
    false
  ),
  (
    'rmarcano@gomezleemarketing.com',
    'Ramon Marcano',
    'user',
    true,
    false,
    false,
    false
  ),
  (
    'lmatos@gomezleemarketing.com',
    'Luis Matos',
    'it',
    true,
    false,
    false,
    false
  ),
  (
    'mgomez@gomezleemarketing.com',
    'Máximo Gomez',
    'leadership',
    true,
    false,
    false,
    false
  )
on conflict (email)
do update set
  full_name = excluded.full_name,
  role = excluded.role,
  is_active = excluded.is_active,
  can_delete_projects = excluded.can_delete_projects,
  can_manage_internal_pricing = excluded.can_manage_internal_pricing,
  can_control_pricing_summary = excluded.can_control_pricing_summary,
  updated_at = now();

alter table public.tablero_cdc_allowed_users enable row level security;

drop policy if exists "tablero_cdc_allowed_users_select_own_active" on public.tablero_cdc_allowed_users;
drop policy if exists "tablero_cdc_allowed_users_no_insert_from_app" on public.tablero_cdc_allowed_users;
drop policy if exists "tablero_cdc_allowed_users_no_update_from_app" on public.tablero_cdc_allowed_users;
drop policy if exists "tablero_cdc_allowed_users_no_delete_from_app" on public.tablero_cdc_allowed_users;

-- La app solo puede leer la fila activa del usuario autenticado.
-- La administración real se hace desde Supabase SQL Editor.
create policy "tablero_cdc_allowed_users_select_own_active"
  on public.tablero_cdc_allowed_users
  for select
  to authenticated
  using (
    is_active = true
    and lower(email) = lower(coalesce(auth.jwt() ->> 'email', ''))
  );

create policy "tablero_cdc_allowed_users_no_insert_from_app"
  on public.tablero_cdc_allowed_users
  for insert
  to authenticated
  with check (false);

create policy "tablero_cdc_allowed_users_no_update_from_app"
  on public.tablero_cdc_allowed_users
  for update
  to authenticated
  using (false)
  with check (false);

create policy "tablero_cdc_allowed_users_no_delete_from_app"
  on public.tablero_cdc_allowed_users
  for delete
  to authenticated
  using (false);

grant select on public.tablero_cdc_allowed_users to authenticated;

-- Funciones auxiliares para políticas/RPC.
create or replace function public.tablero_cdc_current_user_is_allowed()
returns boolean
language sql
stable
security definer
set search_path = public
as $$
  select exists (
    select 1
    from public.tablero_cdc_allowed_users u
    where u.email = lower(coalesce(auth.jwt() ->> 'email', ''))
      and u.is_active = true
  );
$$;

create or replace function public.tablero_cdc_current_user_can_control_pricing_summary()
returns boolean
language sql
stable
security definer
set search_path = public
as $$
  select exists (
    select 1
    from public.tablero_cdc_allowed_users u
    where u.email = lower(coalesce(auth.jwt() ->> 'email', ''))
      and u.is_active = true
      and u.can_control_pricing_summary = true
  );
$$;

grant execute on function public.tablero_cdc_current_user_is_allowed() to authenticated;
grant execute on function public.tablero_cdc_current_user_can_control_pricing_summary() to authenticated;

-- =========================================================
-- Total Tarifado: configuración pública/privada usando tabla de accesos
-- =========================================================

create table if not exists public.tablero_cdc_app_settings (
  key text primary key,
  value jsonb not null default '{}'::jsonb,
  updated_by uuid references auth.users(id),
  updated_at timestamptz not null default now()
);

insert into public.tablero_cdc_app_settings (key, value)
values ('pricing_summary_public', jsonb_build_object('enabled', false))
on conflict (key) do nothing;

alter table public.tablero_cdc_app_settings enable row level security;

drop policy if exists "tablero_cdc_app_settings_select_authenticated" on public.tablero_cdc_app_settings;
drop policy if exists "tablero_cdc_app_settings_select_allowed_users" on public.tablero_cdc_app_settings;
drop policy if exists "tablero_cdc_app_settings_insert_summary_controllers" on public.tablero_cdc_app_settings;
drop policy if exists "tablero_cdc_app_settings_update_summary_controllers" on public.tablero_cdc_app_settings;
drop policy if exists "tablero_cdc_app_settings_delete_none" on public.tablero_cdc_app_settings;

create policy "tablero_cdc_app_settings_select_allowed_users"
  on public.tablero_cdc_app_settings
  for select
  to authenticated
  using (public.tablero_cdc_current_user_is_allowed());

create policy "tablero_cdc_app_settings_insert_summary_controllers"
  on public.tablero_cdc_app_settings
  for insert
  to authenticated
  with check (
    key = 'pricing_summary_public'
    and public.tablero_cdc_current_user_can_control_pricing_summary()
  );

create policy "tablero_cdc_app_settings_update_summary_controllers"
  on public.tablero_cdc_app_settings
  for update
  to authenticated
  using (
    key = 'pricing_summary_public'
    and public.tablero_cdc_current_user_can_control_pricing_summary()
  )
  with check (
    key = 'pricing_summary_public'
    and public.tablero_cdc_current_user_can_control_pricing_summary()
  );

create policy "tablero_cdc_app_settings_delete_none"
  on public.tablero_cdc_app_settings
  for delete
  to authenticated
  using (false);

create or replace function public.set_tablero_cdc_app_settings_updated_at()
returns trigger
language plpgsql
as $$
begin
  new.updated_at = now();
  new.updated_by = auth.uid();
  return new;
end;
$$;

drop trigger if exists trg_tablero_cdc_app_settings_updated_at on public.tablero_cdc_app_settings;

create trigger trg_tablero_cdc_app_settings_updated_at
before insert or update on public.tablero_cdc_app_settings
for each row
execute function public.set_tablero_cdc_app_settings_updated_at();

grant select on public.tablero_cdc_app_settings to authenticated;

create or replace function public.tablero_cdc_set_pricing_summary_public(p_enabled boolean)
returns jsonb
language plpgsql
security definer
set search_path = public
as $$
declare
  v_enabled boolean := coalesce(p_enabled, false);
begin
  if not public.tablero_cdc_current_user_can_control_pricing_summary() then
    raise exception 'No tienes permiso para cambiar la visibilidad del total tarifado.';
  end if;

  insert into public.tablero_cdc_app_settings (key, value, updated_by, updated_at)
  values (
    'pricing_summary_public',
    jsonb_build_object('enabled', v_enabled),
    auth.uid(),
    now()
  )
  on conflict (key)
  do update set
    value = excluded.value,
    updated_by = auth.uid(),
    updated_at = now();

  return jsonb_build_object('enabled', v_enabled);
end;
$$;

grant execute on function public.tablero_cdc_set_pricing_summary_public(boolean) to authenticated;

-- Reemplaza la RPC de resumen para respetar:
-- 1) que el usuario esté autorizado para la app;
-- 2) que sea controlador del Total Tarifado o que el total esté público.
create or replace function public.tablero_cdc_get_pricing_summary(
  p_tab text default 'todos',
  p_search text default '',
  p_country text default '',
  p_brand text default '',
  p_client text default '',
  p_cm text default ''
)
returns jsonb
language sql
stable
security invoker
set search_path = public
as $$
  with visibility as (
    select coalesce((value ->> 'enabled')::boolean, false) as is_public
    from public.tablero_cdc_app_settings
    where key = 'pricing_summary_public'
  ),
  allowed as (
    select
      public.tablero_cdc_current_user_is_allowed()
      and (
        public.tablero_cdc_current_user_can_control_pricing_summary()
        or coalesce((select is_public from visibility), false)
      ) as can_view_pricing
  ),
  params as (
    select
      lower(coalesce(nullif(trim(p_tab), ''), 'todos')) as tab,
      trim(coalesce(p_search, '')) as search_text,
      trim(coalesce(p_country, '')) as country_filter,
      trim(coalesce(p_brand, '')) as brand_filter,
      trim(coalesce(p_client, '')) as client_filter,
      trim(coalesce(p_cm, '')) as cm_filter
  ),
  base_filtered as (
    select p.*
    from public.tablero_cdc_projects p
    cross join params prm
    where
      case
        when prm.tab in ('abiertos', 'activos', 'active', 'open') then
          coalesce(nullif(trim(p.status), ''), 'Activo') = 'Activo'
        when prm.tab in ('cerrados', 'closed') then
          coalesce(nullif(trim(p.status), ''), 'Activo') <> 'Activo'
        else
          true
      end
      and (
        prm.search_text = ''
        or coalesce(p.title, '') ilike '%' || prm.search_text || '%'
        or coalesce(p.client, '') ilike '%' || prm.search_text || '%'
        or coalesce(p.brand, '') ilike '%' || prm.search_text || '%'
        or coalesce(p.country, '') ilike '%' || prm.search_text || '%'
        or coalesce(p.requested_by, '') ilike '%' || prm.search_text || '%'
        or coalesce(p.country_manager, '') ilike '%' || prm.search_text || '%'
        or coalesce(p.description, '') ilike '%' || prm.search_text || '%'
      )
  ),
  filtered as (
    select bf.*
    from base_filtered bf
    cross join params prm
    where
      (prm.country_filter = '' or coalesce(bf.country, '') ilike '%' || prm.country_filter || '%')
      and (prm.brand_filter = '' or coalesce(bf.brand, '') ilike '%' || prm.brand_filter || '%')
      and (prm.client_filter = '' or coalesce(bf.client, '') ilike '%' || prm.client_filter || '%')
      and (prm.cm_filter = '' or coalesce(bf.country_manager, '') ilike '%' || prm.cm_filter || '%')
  ),
  totals as (
    select
      count(*)::integer as project_count,
      coalesce(
        sum(
          greatest(
            coalesce(nullif(trim(internal_amount::text), '')::numeric, 0),
            0
          )
        ),
        0
      )::numeric as total_amount
    from filtered
  )
  select case
    when (select can_view_pricing from allowed) then
      jsonb_build_object(
        'total_amount', (select total_amount from totals),
        'project_count', (select project_count from totals)
      )
    else
      jsonb_build_object(
        'total_amount', 0,
        'project_count', 0
      )
  end;
$$;

grant execute on function public.tablero_cdc_get_pricing_summary(text, text, text, text, text, text) to authenticated;

-- Intenta habilitar realtime para que el cambio de visible/oculto se refleje sin recargar.
do $$
begin
  alter publication supabase_realtime add table public.tablero_cdc_app_settings;
exception
  when duplicate_object then null;
  when undefined_object then null;
end $$;

commit;

select
  'Acceso Tablero CDC listo' as status,
  count(*) filter (where is_active) as usuarios_activos,
  count(*) filter (where can_control_pricing_summary and is_active) as controlan_total_tarifado,
  count(*) filter (where can_manage_internal_pricing and is_active) as ven_interno_cargado,
  count(*) filter (where can_delete_projects and is_active) as pueden_eliminar
from public.tablero_cdc_allowed_users;
