-- ============================================================================
-- SCHEMA: education
-- TABLE: courses
-- DESCRIPTION: Cursos de trading y educacion financiera
-- VERSION: 1.0.0
-- CREATED: 2026-01-16
-- SPRINT: Sprint 2 - DDL Implementation Roadmap Q1-2026
-- ============================================================================

-- Enum para tipo de curso
DO $$ BEGIN
    CREATE TYPE education.course_type AS ENUM (
        'course',           -- Curso completo
        'workshop',         -- Taller practico
        'masterclass',      -- Masterclass
        'webinar',          -- Webinar grabado
        'bootcamp',         -- Bootcamp intensivo
        'certification'     -- Programa de certificacion
    );
EXCEPTION
    WHEN duplicate_object THEN null;
END $$;

-- Enum para modelo de acceso
DO $$ BEGIN
    CREATE TYPE education.access_model AS ENUM (
        'free',             -- Gratis
        'freemium',         -- Gratis con contenido premium
        'paid',             -- De pago
        'subscription',     -- Requiere suscripcion VIP
        'bundle'            -- Parte de un bundle
    );
EXCEPTION
    WHEN duplicate_object THEN null;
END $$;

-- Tabla de Cursos
CREATE TABLE IF NOT EXISTS education.courses (
    -- Identificadores
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES tenants.tenants(id) ON DELETE CASCADE,
    category_id UUID REFERENCES education.categories(id) ON DELETE SET NULL,

    -- Informacion basica
    title VARCHAR(200) NOT NULL,
    slug VARCHAR(200) NOT NULL,
    subtitle VARCHAR(255),
    description TEXT,
    short_description VARCHAR(500),

    -- Clasificacion
    type education.course_type NOT NULL DEFAULT 'course',
    difficulty education.difficulty_level NOT NULL DEFAULT 'beginner',

    -- Instructor/Autor
    instructor_id UUID REFERENCES users.users(id),
    instructor_name VARCHAR(100),
    instructor_bio TEXT,
    instructor_avatar_url TEXT,

    -- Media
    thumbnail_url TEXT,
    banner_url TEXT,
    preview_video_url TEXT,
    trailer_url TEXT,

    -- Contenido
    objectives JSONB DEFAULT '[]'::JSONB,           -- Array de objetivos de aprendizaje
    requirements JSONB DEFAULT '[]'::JSONB,         -- Prerrequisitos
    target_audience JSONB DEFAULT '[]'::JSONB,      -- Publico objetivo
    syllabus JSONB DEFAULT '[]'::JSONB,             -- Temario resumido

    -- Duracion y estructura
    estimated_duration_minutes INTEGER,              -- Duracion total estimada
    total_lessons INTEGER NOT NULL DEFAULT 0,
    total_quizzes INTEGER NOT NULL DEFAULT 0,
    total_modules INTEGER NOT NULL DEFAULT 0,

    -- Acceso y precio
    access_model education.access_model NOT NULL DEFAULT 'free',
    price DECIMAL(10, 2) DEFAULT 0,
    currency VARCHAR(3) DEFAULT 'USD',
    discount_price DECIMAL(10, 2),
    discount_ends_at TIMESTAMPTZ,

    -- Requisitos de suscripcion
    required_vip_tier VARCHAR(50),                  -- NULL = no requiere VIP
    credits_cost INTEGER DEFAULT 0,                 -- Costo en creditos del wallet

    -- Estado
    status education.publish_status NOT NULL DEFAULT 'draft',
    is_featured BOOLEAN NOT NULL DEFAULT FALSE,
    is_new BOOLEAN NOT NULL DEFAULT TRUE,
    is_bestseller BOOLEAN NOT NULL DEFAULT FALSE,

    -- SEO
    meta_title VARCHAR(100),
    meta_description VARCHAR(255),
    meta_keywords VARCHAR(255)[],

    -- Estadisticas (cache)
    enrollment_count INTEGER NOT NULL DEFAULT 0,
    completion_count INTEGER NOT NULL DEFAULT 0,
    average_rating DECIMAL(3, 2) DEFAULT 0,
    review_count INTEGER NOT NULL DEFAULT 0,
    view_count INTEGER NOT NULL DEFAULT 0,

    -- Certificacion
    has_certificate BOOLEAN NOT NULL DEFAULT FALSE,
    certificate_template_id UUID,
    passing_score INTEGER DEFAULT 70,               -- % minimo para certificado

    -- Gamificacion
    xp_reward INTEGER DEFAULT 0,                    -- XP al completar
    badge_id UUID,                                  -- Badge al completar

    -- Configuracion
    allow_reviews BOOLEAN NOT NULL DEFAULT TRUE,
    allow_discussions BOOLEAN NOT NULL DEFAULT TRUE,
    enforce_sequence BOOLEAN NOT NULL DEFAULT FALSE, -- Forzar orden de lecciones

    -- Metadata
    tags VARCHAR(50)[],
    metadata JSONB DEFAULT '{}'::JSONB,

    -- Timestamps
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    published_at TIMESTAMPTZ,
    last_content_update TIMESTAMPTZ,

    -- Constraints
    CONSTRAINT courses_unique_slug_per_tenant UNIQUE (tenant_id, slug),
    CONSTRAINT courses_price_check CHECK (price >= 0),
    CONSTRAINT courses_rating_check CHECK (average_rating >= 0 AND average_rating <= 5)
);

COMMENT ON TABLE education.courses IS
'Cursos de trading y educacion financiera';

COMMENT ON COLUMN education.courses.enforce_sequence IS
'Si TRUE, el usuario debe completar lecciones en orden';

-- Indices
CREATE INDEX IF NOT EXISTS idx_courses_tenant
    ON education.courses(tenant_id);

CREATE INDEX IF NOT EXISTS idx_courses_category
    ON education.courses(category_id);

CREATE INDEX IF NOT EXISTS idx_courses_instructor
    ON education.courses(instructor_id);

CREATE INDEX IF NOT EXISTS idx_courses_slug
    ON education.courses(tenant_id, slug);

CREATE INDEX IF NOT EXISTS idx_courses_status
    ON education.courses(status)
    WHERE status = 'published';

CREATE INDEX IF NOT EXISTS idx_courses_featured
    ON education.courses(tenant_id, is_featured)
    WHERE is_featured = TRUE AND status = 'published';

CREATE INDEX IF NOT EXISTS idx_courses_difficulty
    ON education.courses(difficulty);

CREATE INDEX IF NOT EXISTS idx_courses_access
    ON education.courses(access_model);

CREATE INDEX IF NOT EXISTS idx_courses_rating
    ON education.courses(average_rating DESC)
    WHERE status = 'published';

CREATE INDEX IF NOT EXISTS idx_courses_popular
    ON education.courses(enrollment_count DESC)
    WHERE status = 'published';

-- GIN index para tags
CREATE INDEX IF NOT EXISTS idx_courses_tags_gin
    ON education.courses USING GIN (tags);

-- Trigger para updated_at
DROP TRIGGER IF EXISTS course_updated_at ON education.courses;
CREATE TRIGGER course_updated_at
    BEFORE UPDATE ON education.courses
    FOR EACH ROW
    EXECUTE FUNCTION education.update_education_timestamp();

-- Trigger para actualizar conteo en categoria
CREATE OR REPLACE FUNCTION education.update_category_course_count()
RETURNS TRIGGER AS $$
BEGIN
    -- Decrementar categoria anterior
    IF OLD IS NOT NULL AND OLD.category_id IS NOT NULL THEN
        UPDATE education.categories
        SET course_count = course_count - 1
        WHERE id = OLD.category_id;
    END IF;

    -- Incrementar categoria nueva
    IF NEW IS NOT NULL AND NEW.category_id IS NOT NULL AND NEW.status = 'published' THEN
        UPDATE education.categories
        SET course_count = course_count + 1
        WHERE id = NEW.category_id;
    END IF;

    RETURN COALESCE(NEW, OLD);
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS course_category_count ON education.courses;
CREATE TRIGGER course_category_count
    AFTER INSERT OR UPDATE OF category_id, status OR DELETE ON education.courses
    FOR EACH ROW
    EXECUTE FUNCTION education.update_category_course_count();

-- Vista de cursos publicados
CREATE OR REPLACE VIEW education.v_published_courses AS
SELECT
    c.id,
    c.tenant_id,
    c.category_id,
    cat.name AS category_name,
    c.title,
    c.slug,
    c.subtitle,
    c.short_description,
    c.type,
    c.difficulty,
    c.instructor_name,
    c.thumbnail_url,
    c.estimated_duration_minutes,
    c.total_lessons,
    c.access_model,
    c.price,
    c.discount_price,
    c.is_featured,
    c.is_new,
    c.is_bestseller,
    c.enrollment_count,
    c.average_rating,
    c.review_count,
    c.has_certificate,
    c.tags
FROM education.courses c
LEFT JOIN education.categories cat ON c.category_id = cat.id
WHERE c.status = 'published'
ORDER BY c.is_featured DESC, c.enrollment_count DESC;

-- Vista de cursos populares
CREATE OR REPLACE VIEW education.v_popular_courses AS
SELECT *
FROM education.v_published_courses
ORDER BY enrollment_count DESC
LIMIT 20;

-- RLS Policy para multi-tenancy
ALTER TABLE education.courses ENABLE ROW LEVEL SECURITY;

CREATE POLICY courses_tenant_isolation ON education.courses
    FOR ALL
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

-- Grants
GRANT SELECT, INSERT, UPDATE, DELETE ON education.courses TO trading_app;
GRANT SELECT ON education.courses TO trading_readonly;
GRANT SELECT ON education.v_published_courses TO trading_app;
GRANT SELECT ON education.v_popular_courses TO trading_app;
