-- =============================================================================
-- Migration: 20260419000016_tenants_calendario_hardening
-- Sessão 7 — Tenants + Calendário scan (corrige críticos + altos + WITH CHECKs).
--
-- Resolve:
--   • Tenants V#1 (P0) — tenant_invites RLS off + 0 policies
--   • Tenants V#2 — profiles_insert_own sem WITH CHECK
--   • Tenants V#3 — support_sessions_saas_insert sem WITH CHECK
--   • Tenants V#6 — user_settings_insert_own sem WITH CHECK
--   • Calendário V#1 — feriados_insert + feriados_saas_insert sem WITH CHECK
--
-- Auditoria prévia: tenant_invites tem 0 rows (seguro habilitar RLS sem
-- migração de dados).
-- =============================================================================

-- ─────────────────────────────────────────────────────────────────────────
-- Tenants V#1 (P0): tenant_invites
-- -----------------------------------------------------------------------------
ALTER TABLE public.tenant_invites ENABLE ROW LEVEL SECURITY;

REVOKE ALL ON public.tenant_invites FROM anon, authenticated;
GRANT  SELECT, INSERT, UPDATE, DELETE ON public.tenant_invites TO authenticated;

-- SELECT: tenant_admin/admin/owner do tenant + saas_admin
DROP POLICY IF EXISTS tenant_invites_select ON public.tenant_invites;
CREATE POLICY tenant_invites_select ON public.tenant_invites
  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'
        AND tm.role IN ('tenant_admin','admin','owner')
    )
  );

-- INSERT: só tenant_admin do tenant_id, e invited_by deve ser o caller
DROP POLICY IF EXISTS tenant_invites_insert ON public.tenant_invites;
CREATE POLICY tenant_invites_insert ON public.tenant_invites
  FOR INSERT TO authenticated
  WITH CHECK (
    invited_by = auth.uid()
    AND 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','owner')
    )
  );

-- UPDATE: só revogação por tenant_admin do tenant. Aceitar é via RPC tenant_accept_invite (SECURITY DEFINER).
DROP POLICY IF EXISTS tenant_invites_update ON public.tenant_invites;
CREATE POLICY tenant_invites_update ON public.tenant_invites
  FOR UPDATE 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','owner')
    )
  )
  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','owner')
    )
  );

-- DELETE: tenant_admin OR saas_admin
DROP POLICY IF EXISTS tenant_invites_delete ON public.tenant_invites;
CREATE POLICY tenant_invites_delete ON public.tenant_invites
  FOR DELETE 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','owner')
    )
  );

COMMENT ON TABLE public.tenant_invites IS
  'Convites pra entrar em tenant. Aceitar deve ser via RPC tenant_accept_invite (SECURITY DEFINER). Criar/revogar via UI por tenant_admin.';

-- ─────────────────────────────────────────────────────────────────────────
-- Tenants V#2: profiles INSERT WITH CHECK
-- -----------------------------------------------------------------------------
DROP POLICY IF EXISTS profiles_insert_own ON public.profiles;
CREATE POLICY profiles_insert_own ON public.profiles
  FOR INSERT TO authenticated
  WITH CHECK (id = auth.uid());

-- ─────────────────────────────────────────────────────────────────────────
-- Tenants V#3: support_sessions INSERT WITH CHECK
-- (admin_id deve ser o caller E o caller deve ser saas_admin)
-- -----------------------------------------------------------------------------
DROP POLICY IF EXISTS support_sessions_saas_insert ON public.support_sessions;
CREATE POLICY support_sessions_saas_insert ON public.support_sessions
  FOR INSERT TO authenticated
  WITH CHECK (
    admin_id = auth.uid()
    AND EXISTS (SELECT 1 FROM public.saas_admins sa WHERE sa.user_id = auth.uid())
  );

-- ─────────────────────────────────────────────────────────────────────────
-- Tenants V#6: user_settings INSERT WITH CHECK
-- -----------------------------------------------------------------------------
DROP POLICY IF EXISTS user_settings_insert_own ON public.user_settings;
CREATE POLICY user_settings_insert_own ON public.user_settings
  FOR INSERT TO authenticated
  WITH CHECK (user_id = auth.uid());

-- ─────────────────────────────────────────────────────────────────────────
-- Calendário V#1: feriados INSERT WITH CHECK (tenant + global)
-- -----------------------------------------------------------------------------
DROP POLICY IF EXISTS feriados_insert ON public.feriados;
CREATE POLICY feriados_insert ON public.feriados
  FOR INSERT TO authenticated
  WITH CHECK (
    tenant_id IS NOT NULL
    AND owner_id = auth.uid()
    AND tenant_id IN (
      SELECT tm.tenant_id FROM public.tenant_members tm
      WHERE tm.user_id = auth.uid() AND tm.status = 'active'
    )
  );

DROP POLICY IF EXISTS feriados_saas_insert ON public.feriados;
CREATE POLICY feriados_saas_insert ON public.feriados
  FOR INSERT TO authenticated
  WITH CHECK (
    tenant_id IS NULL
    AND EXISTS (SELECT 1 FROM public.saas_admins sa WHERE sa.user_id = auth.uid())
  );

-- ─────────────────────────────────────────────────────────────────────────
-- Calendário V#2: feriados DELETE — adicionar tenant_admin
-- -----------------------------------------------------------------------------
DROP POLICY IF EXISTS feriados_delete ON public.feriados;
CREATE POLICY feriados_delete ON public.feriados
  FOR DELETE TO authenticated
  USING (
    owner_id = auth.uid()
    OR (tenant_id IS NOT NULL AND 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','owner')
    ))
  );
