-- =============================================================================
-- Migration: 20260418000005_saas_rls_emergency_fix
-- Corrige A#30 (P0) — 7 tabelas SaaS estavam com RLS desabilitado + grants
-- totais pra anon/authenticated/service_role. Qualquer usuário anônimo
-- podia alterar/deletar dados críticos (tenant_features, plan_prices,
-- subscription_intents_personal/tenant, plan_public, ...).
--
-- Estratégia:
--  1. Habilitar RLS em todas as 7 tabelas
--  2. REVOKE ALL de anon (nunca deveria ter tido)
--  3. REVOKE ALL de authenticated (controle passa a ser via policy)
--  4. Policies explícitas por caso de uso
-- =============================================================================

-- ─────────────────────────────────────────────────────────────────────────
-- 1. REVOKE grants inseguros
-- -----------------------------------------------------------------------------
REVOKE ALL ON public.tenant_features               FROM anon, authenticated;
REVOKE ALL ON public.plan_prices                   FROM anon, authenticated;
REVOKE ALL ON public.plan_public                   FROM anon, authenticated;
REVOKE ALL ON public.plan_public_bullets           FROM anon, authenticated;
REVOKE ALL ON public.subscription_intents_personal FROM anon, authenticated;
REVOKE ALL ON public.subscription_intents_tenant   FROM anon, authenticated;
REVOKE ALL ON public.tenant_feature_exceptions_log FROM anon, authenticated;

-- Concede o mínimo necessário (controlado por RLS abaixo)
GRANT SELECT, INSERT, UPDATE, DELETE ON public.tenant_features               TO authenticated;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.plan_prices                   TO authenticated;
GRANT SELECT                         ON public.plan_public                   TO anon, authenticated;
GRANT          INSERT, UPDATE, DELETE ON public.plan_public                  TO authenticated;
GRANT SELECT                         ON public.plan_public_bullets           TO anon, authenticated;
GRANT          INSERT, UPDATE, DELETE ON public.plan_public_bullets          TO authenticated;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.subscription_intents_personal TO authenticated;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.subscription_intents_tenant   TO authenticated;
GRANT SELECT                         ON public.tenant_feature_exceptions_log TO authenticated;

-- ─────────────────────────────────────────────────────────────────────────
-- 2. HABILITAR RLS em todas
-- -----------------------------------------------------------------------------
ALTER TABLE public.tenant_features               ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.plan_prices                   ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.plan_public                   ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.plan_public_bullets           ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.subscription_intents_personal ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.subscription_intents_tenant   ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.tenant_feature_exceptions_log ENABLE ROW LEVEL SECURITY;

-- ─────────────────────────────────────────────────────────────────────────
-- 3. POLICIES — tenant_features
-- -----------------------------------------------------------------------------
-- SELECT: membros do tenant leem as features do próprio tenant. Saas admin lê tudo.
DROP POLICY IF EXISTS tenant_features_select ON public.tenant_features;
CREATE POLICY tenant_features_select ON public.tenant_features
  FOR SELECT TO authenticated
  USING (
    public.is_saas_admin()
    OR tenant_id IN (SELECT tm.tenant_id FROM public.tenant_members tm WHERE tm.user_id = auth.uid() AND tm.status = 'active')
  );

-- WRITE: apenas tenant_admin do próprio tenant OU saas_admin.
DROP POLICY IF EXISTS tenant_features_write ON public.tenant_features;
CREATE POLICY tenant_features_write ON public.tenant_features
  FOR ALL TO authenticated
  USING (
    public.is_saas_admin()
    OR tenant_id IN (
      SELECT tm.tenant_id FROM public.tenant_members tm
      WHERE tm.user_id = auth.uid()
        AND tm.status = 'active'
        AND tm.role IN ('tenant_admin','admin')
    )
  )
  WITH CHECK (
    public.is_saas_admin()
    OR tenant_id IN (
      SELECT tm.tenant_id FROM public.tenant_members tm
      WHERE tm.user_id = auth.uid()
        AND tm.status = 'active'
        AND tm.role IN ('tenant_admin','admin')
    )
  );

-- ─────────────────────────────────────────────────────────────────────────
-- 4. POLICIES — plan_prices (SaaS admin only pra escrita; authenticated lê)
-- -----------------------------------------------------------------------------
DROP POLICY IF EXISTS plan_prices_read ON public.plan_prices;
CREATE POLICY plan_prices_read ON public.plan_prices
  FOR SELECT TO authenticated
  USING (true);  -- preços são públicos pra usuários logados

DROP POLICY IF EXISTS plan_prices_write ON public.plan_prices;
CREATE POLICY plan_prices_write ON public.plan_prices
  FOR ALL TO authenticated
  USING (public.is_saas_admin())
  WITH CHECK (public.is_saas_admin());

-- ─────────────────────────────────────────────────────────────────────────
-- 5. POLICIES — plan_public + plan_public_bullets (anon pode ler — landing page)
-- -----------------------------------------------------------------------------
DROP POLICY IF EXISTS plan_public_read_anon ON public.plan_public;
CREATE POLICY plan_public_read_anon ON public.plan_public
  FOR SELECT TO anon, authenticated
  USING (true);

DROP POLICY IF EXISTS plan_public_write ON public.plan_public;
CREATE POLICY plan_public_write ON public.plan_public
  FOR ALL TO authenticated
  USING (public.is_saas_admin())
  WITH CHECK (public.is_saas_admin());

DROP POLICY IF EXISTS plan_public_bullets_read_anon ON public.plan_public_bullets;
CREATE POLICY plan_public_bullets_read_anon ON public.plan_public_bullets
  FOR SELECT TO anon, authenticated
  USING (true);

DROP POLICY IF EXISTS plan_public_bullets_write ON public.plan_public_bullets;
CREATE POLICY plan_public_bullets_write ON public.plan_public_bullets
  FOR ALL TO authenticated
  USING (public.is_saas_admin())
  WITH CHECK (public.is_saas_admin());

-- ─────────────────────────────────────────────────────────────────────────
-- 6. POLICIES — subscription_intents_personal + _tenant
-- -----------------------------------------------------------------------------
-- Dono vê o próprio intent; saas admin vê tudo; owner cria/atualiza seus próprios.
DROP POLICY IF EXISTS subscription_intents_personal_owner ON public.subscription_intents_personal;
CREATE POLICY subscription_intents_personal_owner ON public.subscription_intents_personal
  FOR ALL TO authenticated
  USING (user_id = auth.uid() OR public.is_saas_admin())
  WITH CHECK (user_id = auth.uid() OR public.is_saas_admin());

DROP POLICY IF EXISTS subscription_intents_tenant_member ON public.subscription_intents_tenant;
CREATE POLICY subscription_intents_tenant_member ON public.subscription_intents_tenant
  FOR ALL TO authenticated
  USING (
    public.is_saas_admin()
    OR tenant_id IN (
      SELECT tm.tenant_id FROM public.tenant_members tm
      WHERE tm.user_id = auth.uid()
        AND tm.status = 'active'
        AND tm.role IN ('tenant_admin','admin')
    )
  )
  WITH CHECK (
    public.is_saas_admin()
    OR tenant_id IN (
      SELECT tm.tenant_id FROM public.tenant_members tm
      WHERE tm.user_id = auth.uid()
        AND tm.status = 'active'
        AND tm.role IN ('tenant_admin','admin')
    )
  );

-- ─────────────────────────────────────────────────────────────────────────
-- 7. POLICY — tenant_feature_exceptions_log (somente leitura)
-- -----------------------------------------------------------------------------
-- Log de auditoria. Inserts vêm de triggers/funções server-side (SECURITY DEFINER).
DROP POLICY IF EXISTS tenant_feature_exceptions_log_read ON public.tenant_feature_exceptions_log;
CREATE POLICY tenant_feature_exceptions_log_read ON public.tenant_feature_exceptions_log
  FOR SELECT TO authenticated
  USING (
    public.is_saas_admin()
    OR tenant_id IN (SELECT tm.tenant_id FROM public.tenant_members tm WHERE tm.user_id = auth.uid() AND tm.status = 'active')
  );

COMMENT ON TABLE public.tenant_features IS
'Controle de features por tenant. RLS: member do tenant lê; tenant_admin ou saas_admin escreve. Antes da migration 20260418000005 estava com RLS off + GRANT ALL pra anon (A#30).';
