-- ============================================================
-- Migration 001: Create base tables
-- Contract: DATA_MODEL.md — do not add tables without approval (Nivel 3)
-- Dependency order: organizations, consent_versions → surveys → questions
--                   → consent_records → responses → answers
-- ============================================================

-- organizations: empresas cliente
CREATE TABLE IF NOT EXISTS public.organizations (
    id          uuid        PRIMARY KEY DEFAULT gen_random_uuid(),
    name        text        NOT NULL,
    sector      text,
    size_bucket text,
    created_at  timestamptz NOT NULL DEFAULT now()
);

-- consent_versions: textos de consentimiento versionados (INMUTABLES — ver migration 004)
CREATE TABLE IF NOT EXISTS public.consent_versions (
    id         uuid        PRIMARY KEY DEFAULT gen_random_uuid(),
    version    text        NOT NULL UNIQUE,
    body       text        NOT NULL,
    scopes     jsonb       NOT NULL,
    created_at timestamptz NOT NULL DEFAULT now()
);

-- surveys: definición de cada estudio
-- Dos ejes de clasificación ortogonales (ADR-001 §2):
--   data_sensitivity → consentimiento / seguridad legal
--   security_class   → RLS / cifrado (ORTOGONAL al anterior)
CREATE TABLE IF NOT EXISTS public.surveys (
    id                 uuid        PRIMARY KEY DEFAULT gen_random_uuid(),
    org_id             uuid        NOT NULL REFERENCES public.organizations(id),
    title              text        NOT NULL,
    status             text        NOT NULL DEFAULT 'draft'
                                   CHECK (status IN ('draft', 'live', 'closed')),
    -- Eje 1: anonimato — irreversible una vez publicada
    is_anonymous       boolean     NOT NULL,
    -- Eje 2a: sensibilidad legal → alimenta consentimiento
    data_sensitivity   text        NOT NULL
                                   CHECK (data_sensitivity IN ('comun', 'sensible', 'anonimizado')),
    -- Eje 2b: seguridad → alimenta RLS/cifrado (ORTOGONAL al anterior)
    security_class     text        NOT NULL
                                   CHECK (security_class IN ('publico', 'interno', 'confidencial')),
    -- Rol de responsable (Modo A = nosotros; Modo B = empresa. v1 solo usa A)
    controller_role    text        NOT NULL DEFAULT 'A'
                                   CHECK (controller_role IN ('A', 'B')),
    consent_version_id uuid        REFERENCES public.consent_versions(id),
    brand_config       jsonb,
    -- Umbral de k-anonimato mandatorio (regla no negociable #3 CLAUDE.md)
    k_threshold        int         NOT NULL DEFAULT 5 CHECK (k_threshold > 0),
    created_at         timestamptz NOT NULL DEFAULT now(),
    published_at       timestamptz
);

-- questions: preguntas de la encuesta
-- is_sensitive: auto-true para tipos salud/discapacidad (ver trigger en migration 004)
CREATE TABLE IF NOT EXISTS public.questions (
    id                uuid        PRIMARY KEY DEFAULT gen_random_uuid(),
    survey_id         uuid        NOT NULL REFERENCES public.surveys(id) ON DELETE CASCADE,
    code              text        NOT NULL,
    type              text        NOT NULL
                                  CHECK (type IN (
                                      'text_short', 'text_long',
                                      'single_choice', 'multiple_choice',
                                      'rating', 'nps', 'matrix', 'ranking',
                                      'date', 'slider', 'yes_no', 'section'
                                  )),
    prompt            text        NOT NULL,
    position          int         NOT NULL,
    is_sensitive      boolean     NOT NULL DEFAULT false,
    max_select        int,
    options           jsonb,
    -- Formato: [{ "if_question": "CODE", "op": "eq", "value": "yes", "action": "show|hide|skip", "target": "CODE" }]
    conditional_rules jsonb,
    required          boolean     NOT NULL DEFAULT false,
    UNIQUE (survey_id, code),
    UNIQUE (survey_id, position)
);

-- consent_records: qué consintió cada respuesta (INMUTABLE — ver trigger en migration 004)
-- Sin UPDATE/DELETE — se inserta una vez junto con cada response
CREATE TABLE IF NOT EXISTS public.consent_records (
    id                 uuid        PRIMARY KEY DEFAULT gen_random_uuid(),
    consent_version_id uuid        NOT NULL REFERENCES public.consent_versions(id),
    granted_scopes     jsonb       NOT NULL,
    granted_at         timestamptz NOT NULL DEFAULT now()
);

-- responses: una submission
-- respondent_id RESERVADO y NULL en encuestas anónimas (regla no negociable #2 CLAUDE.md)
-- Trigger en migration 004 rechaza respondent_id no nulo cuando is_anonymous=true
-- Cuasi-identificadores en bucket — minimización: rango etario, no fecha exacta
CREATE TABLE IF NOT EXISTS public.responses (
    id                uuid        PRIMARY KEY DEFAULT gen_random_uuid(),
    survey_id         uuid        NOT NULL REFERENCES public.surveys(id),
    company_id        uuid        NOT NULL REFERENCES public.organizations(id),
    respondent_id     uuid,                -- RESERVADO, NULL en v1 (encuestas anónimas)
    ip_hash           text,                -- SHA-256 + salt, dedup sin identidad
    consent_record_id uuid        NOT NULL REFERENCES public.consent_records(id),
    submitted_at      timestamptz NOT NULL DEFAULT now(),
    -- Cuasi-identificadores denormalizados para segmentación eficiente
    qi_age_bucket     text,
    qi_sector         text,
    qi_zone           text
);

-- answers: valor de cada pregunta en una submission
-- El texto libre (text_long) NO se expone en agg_segment (regla no negociable #4 CLAUDE.md)
CREATE TABLE IF NOT EXISTS public.answers (
    id          uuid  PRIMARY KEY DEFAULT gen_random_uuid(),
    response_id uuid  NOT NULL REFERENCES public.responses(id) ON DELETE CASCADE,
    question_id uuid  NOT NULL REFERENCES public.questions(id),
    value       jsonb NOT NULL,
    UNIQUE (response_id, question_id)
);

-- ============================================================
-- Indexes
-- ============================================================
CREATE INDEX IF NOT EXISTS idx_surveys_org_id     ON public.surveys(org_id);
CREATE INDEX IF NOT EXISTS idx_surveys_status      ON public.surveys(status);

CREATE INDEX IF NOT EXISTS idx_questions_survey    ON public.questions(survey_id);
CREATE INDEX IF NOT EXISTS idx_questions_position  ON public.questions(survey_id, position);

-- Índice compuesto para agg_segment: filtro por encuesta y agrupación por QIs
CREATE INDEX IF NOT EXISTS idx_responses_survey    ON public.responses(survey_id);
CREATE INDEX IF NOT EXISTS idx_responses_company   ON public.responses(company_id);
CREATE INDEX IF NOT EXISTS idx_responses_ip_hash   ON public.responses(ip_hash);
CREATE INDEX IF NOT EXISTS idx_responses_qi_seg    ON public.responses(survey_id, qi_age_bucket, qi_sector, qi_zone);

CREATE INDEX IF NOT EXISTS idx_answers_response    ON public.answers(response_id);
CREATE INDEX IF NOT EXISTS idx_answers_question    ON public.answers(question_id);

CREATE INDEX IF NOT EXISTS idx_consent_rec_cv      ON public.consent_records(consent_version_id);
