-- =====================================================
-- EMERGES TES - Esquema de Base de Datos
-- FASE 1: Infraestructura Base
-- =====================================================
-- 
-- Este script crea el esquema completo de base de datos
-- para el sistema de gestión de contenido de EMERGES TES.
--
-- IMPORTANTE: Ejecutar en orden, no modificar sin revisión.
-- =====================================================

-- Crear esquema principal
CREATE SCHEMA IF NOT EXISTS emerges_content;

-- Extensión para UUIDs
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

-- =====================================================
-- TABLA: content_items
-- Propósito: Almacena todos los tipos de contenido
-- =====================================================
CREATE TABLE IF NOT EXISTS emerges_content.content_items (
    -- Identificación (inmutable)
    id VARCHAR(100) PRIMARY KEY,
    type VARCHAR(50) NOT NULL,
    level VARCHAR(50) NOT NULL,
    
    -- Contenido (editable)
    title VARCHAR(500) NOT NULL,
    short_title VARCHAR(200),
    content JSONB NOT NULL,
    content_markdown TEXT,
    
    -- Metadatos de contenido
    category VARCHAR(100),
    subcategory VARCHAR(100),
    priority VARCHAR(20),
    age_group VARCHAR(20),
    
    -- Versionado
    version INTEGER NOT NULL DEFAULT 1,
    latest_version INTEGER NOT NULL DEFAULT 1,
    
    -- Estado y validación
    status VARCHAR(20) NOT NULL DEFAULT 'draft',
    validated_by VARCHAR(100),
    validated_at TIMESTAMP WITH TIME ZONE,
    clinical_source VARCHAR(200),
    quality_score INTEGER,
    
    -- Revisión
    reviewed_by VARCHAR(100),
    reviewed_at TIMESTAMP WITH TIME ZONE,
    
    -- Auditoría
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
    created_by VARCHAR(100) NOT NULL,
    updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
    updated_by VARCHAR(100) NOT NULL,
    
    -- Constraints
    CONSTRAINT chk_type CHECK (type IN ('protocol', 'guide', 'manual', 'drug')),
    CONSTRAINT chk_level CHECK (level IN ('operativo', 'formativo', 'referencia')),
    CONSTRAINT chk_status CHECK (status IN ('draft', 'pending', 'validated', 'rejected', 'archived')),
    CONSTRAINT chk_priority CHECK (priority IN ('critico', 'alto', 'medio', 'bajo') OR priority IS NULL),
    CONSTRAINT chk_quality_score CHECK (quality_score IS NULL OR (quality_score >= 0 AND quality_score <= 100))
);

-- Índices para content_items
CREATE INDEX IF NOT EXISTS idx_content_items_type ON emerges_content.content_items(type);
CREATE INDEX IF NOT EXISTS idx_content_items_level ON emerges_content.content_items(level);
CREATE INDEX IF NOT EXISTS idx_content_items_status ON emerges_content.content_items(status);
CREATE INDEX IF NOT EXISTS idx_content_items_category ON emerges_content.content_items(category);
CREATE INDEX IF NOT EXISTS idx_content_items_validated_at ON emerges_content.content_items(validated_at);
CREATE INDEX IF NOT EXISTS idx_content_items_updated_at ON emerges_content.content_items(updated_at);
CREATE INDEX IF NOT EXISTS idx_content_items_content_gin ON emerges_content.content_items USING GIN (content);
CREATE INDEX IF NOT EXISTS idx_content_items_title_fts ON emerges_content.content_items USING GIN (to_tsvector('spanish', title));

-- =====================================================
-- TABLA: content_versions
-- Propósito: Historial de versiones
-- =====================================================
CREATE TABLE IF NOT EXISTS emerges_content.content_versions (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    content_id VARCHAR(100) NOT NULL,
    version INTEGER NOT NULL,
    
    -- Snapshot del contenido
    content JSONB NOT NULL,
    content_markdown TEXT,
    title VARCHAR(500) NOT NULL,
    
    -- Metadatos de la versión
    status VARCHAR(20) NOT NULL,
    validated_by VARCHAR(100),
    validated_at TIMESTAMP WITH TIME ZONE,
    clinical_source VARCHAR(200),
    
    -- Cambios
    change_summary TEXT,
    changed_fields TEXT[],
    
    -- Auditoría
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
    created_by VARCHAR(100) NOT NULL,
    
    -- Constraints
    CONSTRAINT fk_content_versions_content_id 
        FOREIGN KEY (content_id) 
        REFERENCES emerges_content.content_items(id) 
        ON DELETE CASCADE,
    CONSTRAINT chk_version_status CHECK (status IN ('draft', 'pending', 'validated', 'rejected', 'archived')),
    CONSTRAINT uq_content_versions_content_version UNIQUE (content_id, version)
);

-- Índices para content_versions
CREATE INDEX IF NOT EXISTS idx_content_versions_content_id ON emerges_content.content_versions(content_id);
CREATE INDEX IF NOT EXISTS idx_content_versions_version ON emerges_content.content_versions(version);
CREATE INDEX IF NOT EXISTS idx_content_versions_created_at ON emerges_content.content_versions(created_at);

-- =====================================================
-- TABLA: content_relations
-- Propósito: Relaciones entre contenidos
-- =====================================================
CREATE TABLE IF NOT EXISTS emerges_content.content_relations (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    source_id VARCHAR(100) NOT NULL,
    target_id VARCHAR(100) NOT NULL,
    relation_type VARCHAR(50) NOT NULL,
    
    -- Metadatos
    is_primary BOOLEAN DEFAULT false,
    order_index INTEGER,
    
    -- Auditoría
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
    created_by VARCHAR(100) NOT NULL,
    updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
    
    -- Constraints
    CONSTRAINT fk_content_relations_source 
        FOREIGN KEY (source_id) 
        REFERENCES emerges_content.content_items(id) 
        ON DELETE CASCADE,
    CONSTRAINT fk_content_relations_target 
        FOREIGN KEY (target_id) 
        REFERENCES emerges_content.content_items(id) 
        ON DELETE CASCADE,
    CONSTRAINT chk_relation_type CHECK (relation_type IN ('has_guide', 'has_manual', 'references', 'related_to')),
    CONSTRAINT uq_content_relations_source_target_type UNIQUE (source_id, target_id, relation_type)
);

-- Índices para content_relations
CREATE INDEX IF NOT EXISTS idx_content_relations_source ON emerges_content.content_relations(source_id);
CREATE INDEX IF NOT EXISTS idx_content_relations_target ON emerges_content.content_relations(target_id);
CREATE INDEX IF NOT EXISTS idx_content_relations_type ON emerges_content.content_relations(relation_type);

-- =====================================================
-- TABLA: content_change_log
-- Propósito: Log de auditoría
-- =====================================================
CREATE TABLE IF NOT EXISTS emerges_content.content_change_log (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    content_id VARCHAR(100) NOT NULL,
    version INTEGER NOT NULL,
    
    -- Cambio
    action VARCHAR(20) NOT NULL,
    field_path VARCHAR(200),
    old_value JSONB,
    new_value JSONB,
    
    -- Contexto
    change_reason TEXT,
    comment TEXT,
    
    -- Auditoría
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
    created_by VARCHAR(100) NOT NULL,
    ip_address INET,
    user_agent TEXT,
    
    -- Constraints
    CONSTRAINT fk_content_change_log_content 
        FOREIGN KEY (content_id) 
        REFERENCES emerges_content.content_items(id) 
        ON DELETE CASCADE,
    CONSTRAINT chk_change_log_action CHECK (action IN ('create', 'update', 'delete', 'validate', 'reject', 'archive'))
);

-- Índices para content_change_log
CREATE INDEX IF NOT EXISTS idx_content_change_log_content_id ON emerges_content.content_change_log(content_id);
CREATE INDEX IF NOT EXISTS idx_content_change_log_version ON emerges_content.content_change_log(version);
CREATE INDEX IF NOT EXISTS idx_content_change_log_created_at ON emerges_content.content_change_log(created_at);
CREATE INDEX IF NOT EXISTS idx_content_change_log_created_by ON emerges_content.content_change_log(created_by);

-- =====================================================
-- TABLA: users
-- Propósito: Usuarios del panel administrador
-- =====================================================
CREATE TABLE IF NOT EXISTS emerges_content.users (
    id VARCHAR(100) PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,
    name VARCHAR(200) NOT NULL,
    role VARCHAR(50) NOT NULL,
    
    -- Autenticación
    password_hash VARCHAR(255) NOT NULL,
    salt VARCHAR(255) NOT NULL,
    
    -- Estado
    is_active BOOLEAN DEFAULT true,
    last_login TIMESTAMP WITH TIME ZONE,
    
    -- Metadatos
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
    created_by VARCHAR(100),
    updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
    
    -- Constraints
    CONSTRAINT chk_user_role CHECK (role IN ('admin_clinico', 'editor_docente', 'editor_clinico', 'revisor'))
);

-- Compatibilidad con esquemas previos de users
DO $$
BEGIN
    IF EXISTS (
        SELECT 1
        FROM information_schema.tables
        WHERE table_schema = 'emerges_content'
          AND table_name = 'users'
    ) THEN
        -- Renombrar username -> name si aplica
        IF EXISTS (
            SELECT 1
            FROM information_schema.columns
            WHERE table_schema = 'emerges_content'
              AND table_name = 'users'
              AND column_name = 'username'
        ) AND NOT EXISTS (
            SELECT 1
            FROM information_schema.columns
            WHERE table_schema = 'emerges_content'
              AND table_name = 'users'
              AND column_name = 'name'
        ) THEN
            ALTER TABLE emerges_content.users RENAME COLUMN username TO name;
        END IF;

        -- Columnas faltantes
        IF NOT EXISTS (
            SELECT 1
            FROM information_schema.columns
            WHERE table_schema = 'emerges_content'
              AND table_name = 'users'
              AND column_name = 'name'
        ) THEN
            ALTER TABLE emerges_content.users ADD COLUMN name VARCHAR(200) NOT NULL DEFAULT '';
        END IF;

        IF NOT EXISTS (
            SELECT 1
            FROM information_schema.columns
            WHERE table_schema = 'emerges_content'
              AND table_name = 'users'
              AND column_name = 'salt'
        ) THEN
            ALTER TABLE emerges_content.users ADD COLUMN salt VARCHAR(255) NOT NULL DEFAULT '';
        END IF;

        IF NOT EXISTS (
            SELECT 1
            FROM information_schema.columns
            WHERE table_schema = 'emerges_content'
              AND table_name = 'users'
              AND column_name = 'created_by'
        ) THEN
            ALTER TABLE emerges_content.users ADD COLUMN created_by VARCHAR(100);
        END IF;

        -- Ajustar tipos si venimos de esquema anterior
        BEGIN
            ALTER TABLE emerges_content.users
                ALTER COLUMN id TYPE VARCHAR(100) USING id::text;
        EXCEPTION WHEN others THEN
            NULL;
        END;

        BEGIN
            ALTER TABLE emerges_content.users
                ALTER COLUMN email TYPE VARCHAR(255);
        EXCEPTION WHEN others THEN
            NULL;
        END;

        BEGIN
            ALTER TABLE emerges_content.users
                ALTER COLUMN role TYPE VARCHAR(50);
        EXCEPTION WHEN others THEN
            NULL;
        END;

        BEGIN
            ALTER TABLE emerges_content.users
                ALTER COLUMN password_hash TYPE VARCHAR(255);
        EXCEPTION WHEN others THEN
            NULL;
        END;

        ALTER TABLE emerges_content.users
            ALTER COLUMN is_active SET DEFAULT true;
    END IF;
END $$;

-- Índices para users
CREATE INDEX IF NOT EXISTS idx_users_email ON emerges_content.users(email);
CREATE INDEX IF NOT EXISTS idx_users_role ON emerges_content.users(role);
CREATE INDEX IF NOT EXISTS idx_users_active ON emerges_content.users(is_active);

-- =====================================================
-- TABLA: content_sync_status
-- Propósito: Estado de sincronización
-- =====================================================
CREATE TABLE IF NOT EXISTS emerges_content.content_sync_status (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    content_id VARCHAR(100) NOT NULL,
    version INTEGER NOT NULL,
    
    -- Sincronización
    synced_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
    sync_count INTEGER DEFAULT 1,
    
    -- Constraints
    CONSTRAINT fk_content_sync_status_content 
        FOREIGN KEY (content_id) 
        REFERENCES emerges_content.content_items(id) 
        ON DELETE CASCADE,
    CONSTRAINT uq_content_sync_status_content_version UNIQUE (content_id, version)
);

-- Índices para content_sync_status
CREATE INDEX IF NOT EXISTS idx_content_sync_status_content_id ON emerges_content.content_sync_status(content_id);
CREATE INDEX IF NOT EXISTS idx_content_sync_status_synced_at ON emerges_content.content_sync_status(synced_at);

-- =====================================================
-- VISTAS ÚTILES
-- =====================================================

-- Vista: Contenido validado (solo lectura pública)
CREATE OR REPLACE VIEW emerges_content.v_validated_content AS
SELECT 
    id,
    type,
    level,
    title,
    short_title,
    content,
    content_markdown,
    category,
    subcategory,
    priority,
    age_group,
    version,
    validated_at,
    clinical_source,
    updated_at
FROM emerges_content.content_items
WHERE status = 'validated'
ORDER BY updated_at DESC;

-- Vista: Contenido pendiente de validación
CREATE OR REPLACE VIEW emerges_content.v_pending_validation AS
SELECT 
    ci.*,
    u.name as created_by_name,
    u.email as created_by_email
FROM emerges_content.content_items ci
LEFT JOIN emerges_content.users u ON ci.created_by = u.id
WHERE ci.status = 'pending'
ORDER BY ci.updated_at ASC;

-- =====================================================
-- COMENTARIOS EN TABLAS
-- =====================================================
COMMENT ON TABLE emerges_content.content_items IS 'Almacena todos los tipos de contenido (protocolos, guías, manual, fármacos)';
COMMENT ON TABLE emerges_content.content_versions IS 'Historial completo de versiones de cada contenido';
COMMENT ON TABLE emerges_content.content_relations IS 'Relaciones entre protocolos, guías y manual';
COMMENT ON TABLE emerges_content.content_change_log IS 'Log detallado de todos los cambios para auditoría';
COMMENT ON TABLE emerges_content.users IS 'Usuarios del panel administrador con roles y permisos';
COMMENT ON TABLE emerges_content.content_sync_status IS 'Trackea qué versiones han sido sincronizadas con las apps';

