-- ============================================================
-- Migration 003: RLS helper functions + policies
--
-- Roles de la plataforma (via JWT custom claim "app_role"):
--   'org_admin'  → empresa cliente: accede solo a agregados de su org, nunca filas crudas
--   'analyst'    → análisis interno (InQ): accede vía service_role que bypasa RLS
--   'respondent' → rellenador de encuesta: puede insertar, no leer
--   (no claim)   → anon: puede leer encuestas live y consentimientos para rellenar el form
--
-- CRÍTICO: ninguna policy devuelve filas crudas de responses/answers a org_admin
-- El acceso de org_admin es SOLO vía la función agg_segment (migration 005)
-- ============================================================

-- ============================================================
-- Funciones helper para leer JWT claims
-- ============================================================
CREATE OR REPLACE FUNCTION public.current_app_role()
RETURNS text
LANGUAGE sql STABLE SECURITY DEFINER
SET search_path = public
AS $$
  SELECT COALESCE(auth.jwt() ->> 'app_role', '')
$$;

CREATE OR REPLACE FUNCTION public.current_org_id()
RETURNS uuid
LANGUAGE sql STABLE SECURITY DEFINER
SET search_path = public
AS $$
  SELECT NULLIF(auth.jwt() ->> 'org_id', '')::uuid
$$;

-- ============================================================
-- organizations
-- org_admin ve solo su propia org; analyst usa service_role
-- ============================================================
CREATE POLICY "org_select_own"
    ON public.organizations FOR SELECT
    TO authenticated
    USING (
        (public.current_app_role() = 'org_admin' AND id = public.current_org_id())
        OR public.current_app_role() = 'analyst'
    );

-- ============================================================
-- consent_versions
-- Cualquiera (incluido anon) puede leer el texto de consentimiento
-- para mostrarlo al respondente antes de que envíe.
-- INSERT: solo via service_role (sin policy de INSERT para auth/anon)
-- UPDATE/DELETE: bloqueados por trigger en migration 004
-- ============================================================
CREATE POLICY "consent_versions_select_all"
    ON public.consent_versions FOR SELECT
    USING (true);

-- ============================================================
-- surveys
-- anon: solo encuestas live (para rellenar el formulario)
-- org_admin: todas sus encuestas en cualquier estado
-- analyst: service_role (bypasa RLS)
-- ============================================================
CREATE POLICY "surveys_select_live_anon"
    ON public.surveys FOR SELECT
    TO anon
    USING (status = 'live');

CREATE POLICY "surveys_select_auth"
    ON public.surveys FOR SELECT
    TO authenticated
    USING (
        public.current_app_role() = 'analyst'
        OR (
            public.current_app_role() = 'org_admin'
            AND org_id = public.current_org_id()
        )
    );

-- ============================================================
-- questions
-- anon: preguntas de encuestas live (necesario para mostrar el form)
-- org_admin: preguntas de sus encuestas
-- ============================================================
CREATE POLICY "questions_select_live"
    ON public.questions FOR SELECT
    TO anon
    USING (
        EXISTS (
            SELECT 1 FROM public.surveys s
            WHERE s.id = survey_id AND s.status = 'live'
        )
    );

CREATE POLICY "questions_select_auth"
    ON public.questions FOR SELECT
    TO authenticated
    USING (
        public.current_app_role() = 'analyst'
        OR (
            public.current_app_role() = 'org_admin'
            AND EXISTS (
                SELECT 1 FROM public.surveys s
                WHERE s.id = survey_id AND s.org_id = public.current_org_id()
            )
        )
    );

-- ============================================================
-- consent_records
-- anon/authenticated pueden INSERT al enviar el formulario
-- SELECT: solo service_role (analyst interno)
-- UPDATE/DELETE: bloqueados por trigger en migration 004
-- ============================================================
CREATE POLICY "consent_records_insert"
    ON public.consent_records FOR INSERT
    TO anon, authenticated
    WITH CHECK (true);

-- ============================================================
-- responses
-- CRÍTICO: NO hay policy SELECT para org_admin ni anon.
-- Resultado: org_admin recibe 0 filas en SELECT directo → solo puede
-- acceder mediante agg_segment, que aplica k_threshold.
-- INSERT: permitido a anon/authenticated solo para encuestas live.
-- ============================================================
CREATE POLICY "responses_insert"
    ON public.responses FOR INSERT
    TO anon, authenticated
    WITH CHECK (
        EXISTS (
            SELECT 1 FROM public.surveys s
            WHERE s.id = survey_id AND s.status = 'live'
        )
    );

-- ============================================================
-- answers
-- Mismo patrón que responses: INSERT permitido, 0 SELECT para org_admin.
-- El texto libre (type='text_long') no se expone en agg_segment (regla #4).
-- ============================================================
CREATE POLICY "answers_insert"
    ON public.answers FOR INSERT
    TO anon, authenticated
    WITH CHECK (
        EXISTS (
            SELECT 1 FROM public.responses r
            WHERE r.id = response_id
        )
    );
