-- =============================================================================
-- F1.2 — Schema-per-tenant: helpers de resolução de schema
-- Adaptação ao modelo multi-membership deste projeto (docs/F0_categorizacao.md D2):
--   profiles.tenant_id é NULL; membership vive em tenant_members (multi-tenant).
--   Logo NÃO existe current_tenant_schema() — RPCs recebem p_tenant_id explícito
--   e validam via tenant_schema_checked(p_tenant_id).
-- =============================================================================

BEGIN;

-- slug -> nome de schema (validado). Retorna NULL se slug inválido.
CREATE OR REPLACE FUNCTION public.tenant_schema_name(p_slug text)
RETURNS text
LANGUAGE sql
IMMUTABLE
AS $$
    SELECT CASE
        WHEN p_slug ~ '^[a-z][a-z0-9_]{1,47}$' THEN 'tenant_' || p_slug
        ELSE NULL
    END;
$$;

-- tenant_id -> nome de schema
CREATE OR REPLACE FUNCTION public.tenant_schema_for(p_tenant_id uuid)
RETURNS text
LANGUAGE sql
STABLE
SECURITY DEFINER
SET search_path TO 'public', 'pg_temp'
AS $$
    SELECT public.tenant_schema_name(t.slug) FROM public.tenants t WHERE t.id = p_tenant_id;
$$;

-- nome de schema -> tenant_id (CRÍTICO pra triggers: a coluna tenant_id não
-- existe mais nas tabelas tenant; o schema é a identidade)
CREATE OR REPLACE FUNCTION public.tenant_id_for_schema(p_schema text)
RETURNS uuid
LANGUAGE sql
STABLE
SECURITY DEFINER
SET search_path TO 'public', 'pg_temp'
AS $$
    SELECT t.id FROM public.tenants t WHERE public.tenant_schema_name(t.slug) = p_schema;
$$;

-- Resolve schema de um tenant COM validação de acesso do usuário logado.
-- Substitui o current_tenant_schema() do blueprint (que assumia 1 tenant/usuário).
CREATE OR REPLACE FUNCTION public.tenant_schema_checked(p_tenant_id uuid)
RETURNS text
LANGUAGE plpgsql
STABLE
SECURITY DEFINER
SET search_path TO 'public', 'pg_temp'
AS $$
DECLARE
    v_schema text;
BEGIN
    IF p_tenant_id IS NULL THEN
        RAISE EXCEPTION 'tenant_schema_checked: p_tenant_id obrigatório';
    END IF;
    IF NOT public.is_tenant_member(p_tenant_id) AND NOT public.is_saas_admin() THEN
        RAISE EXCEPTION 'acesso negado ao tenant %', p_tenant_id
            USING ERRCODE = '42501';
    END IF;
    v_schema := public.tenant_schema_for(p_tenant_id);
    IF v_schema IS NULL THEN
        RAISE EXCEPTION 'tenant % não encontrado ou slug inválido', p_tenant_id;
    END IF;
    RETURN v_schema;
END;
$$;

COMMIT;
