-- ============================================================================
-- SCHEMA: education
-- TABLE: lesson_progress
-- DESCRIPTION: Progreso de usuarios por leccion
-- VERSION: 1.0.0
-- CREATED: 2026-01-16
-- SPRINT: Sprint 2 - DDL Implementation Roadmap Q1-2026
-- ============================================================================

-- Tabla de Progreso por Leccion
CREATE TABLE IF NOT EXISTS education.lesson_progress (
    -- Identificadores
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    enrollment_id UUID NOT NULL REFERENCES education.enrollments(id) ON DELETE CASCADE,
    lesson_id UUID NOT NULL REFERENCES education.lessons(id) ON DELETE CASCADE,
    user_id UUID NOT NULL REFERENCES users.users(id) ON DELETE CASCADE,
    tenant_id UUID NOT NULL REFERENCES tenants.tenants(id) ON DELETE CASCADE,

    -- Estado
    is_started BOOLEAN NOT NULL DEFAULT FALSE,
    is_completed BOOLEAN NOT NULL DEFAULT FALSE,

    -- Progreso de video
    video_progress_percent DECIMAL(5, 2) DEFAULT 0,
    video_position_seconds INTEGER DEFAULT 0,       -- Ultima posicion del video
    video_watched_seconds INTEGER DEFAULT 0,        -- Total segundos vistos
    video_completed BOOLEAN NOT NULL DEFAULT FALSE,

    -- Tiempo
    time_spent_minutes INTEGER NOT NULL DEFAULT 0,
    visit_count INTEGER NOT NULL DEFAULT 1,

    -- Notas del usuario
    user_notes TEXT,
    bookmarked BOOLEAN NOT NULL DEFAULT FALSE,
    bookmark_position_seconds INTEGER,

    -- Quiz asociado (si existe)
    quiz_attempted BOOLEAN NOT NULL DEFAULT FALSE,
    quiz_passed BOOLEAN NOT NULL DEFAULT FALSE,
    quiz_score DECIMAL(5, 2),

    -- Recursos descargados
    resources_downloaded JSONB DEFAULT '[]'::JSONB,

    -- XP ganado
    xp_earned INTEGER NOT NULL DEFAULT 0,

    -- Timestamps
    started_at TIMESTAMPTZ,
    completed_at TIMESTAMPTZ,
    last_accessed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),

    -- Constraints
    CONSTRAINT lesson_progress_unique UNIQUE (enrollment_id, lesson_id),
    CONSTRAINT lesson_progress_video_check CHECK (video_progress_percent BETWEEN 0 AND 100)
);

COMMENT ON TABLE education.lesson_progress IS
'Tracking detallado del progreso de cada usuario en cada leccion';

COMMENT ON COLUMN education.lesson_progress.video_position_seconds IS
'Ultima posicion de reproduccion del video (para continuar donde lo dejo)';

-- Indices
CREATE INDEX IF NOT EXISTS idx_lesson_progress_enrollment
    ON education.lesson_progress(enrollment_id);

CREATE INDEX IF NOT EXISTS idx_lesson_progress_lesson
    ON education.lesson_progress(lesson_id);

CREATE INDEX IF NOT EXISTS idx_lesson_progress_user
    ON education.lesson_progress(user_id);

CREATE INDEX IF NOT EXISTS idx_lesson_progress_tenant
    ON education.lesson_progress(tenant_id);

CREATE INDEX IF NOT EXISTS idx_lesson_progress_completed
    ON education.lesson_progress(enrollment_id, is_completed)
    WHERE is_completed = TRUE;

CREATE INDEX IF NOT EXISTS idx_lesson_progress_in_progress
    ON education.lesson_progress(enrollment_id, lesson_id)
    WHERE is_started = TRUE AND is_completed = FALSE;

CREATE INDEX IF NOT EXISTS idx_lesson_progress_bookmarked
    ON education.lesson_progress(user_id, bookmarked)
    WHERE bookmarked = TRUE;

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

-- Trigger para actualizar started_at y completed_at
CREATE OR REPLACE FUNCTION education.update_lesson_progress_timestamps()
RETURNS TRIGGER AS $$
BEGIN
    -- Marcar inicio
    IF NEW.is_started = TRUE AND OLD.is_started = FALSE THEN
        NEW.started_at = NOW();
    END IF;

    -- Marcar completado
    IF NEW.is_completed = TRUE AND OLD.is_completed = FALSE THEN
        NEW.completed_at = NOW();

        -- Otorgar XP si no se ha ganado
        IF NEW.xp_earned = 0 THEN
            SELECT xp_reward INTO NEW.xp_earned
            FROM education.lessons
            WHERE id = NEW.lesson_id;
        END IF;
    END IF;

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS lesson_progress_timestamps ON education.lesson_progress;
CREATE TRIGGER lesson_progress_timestamps
    BEFORE UPDATE OF is_started, is_completed ON education.lesson_progress
    FOR EACH ROW
    EXECUTE FUNCTION education.update_lesson_progress_timestamps();

-- Trigger para recalcular progreso del enrollment
CREATE OR REPLACE FUNCTION education.recalculate_enrollment_on_lesson()
RETURNS TRIGGER AS $$
BEGIN
    -- Recalcular progreso del enrollment
    PERFORM education.calculate_enrollment_progress(NEW.enrollment_id);

    -- Actualizar tiempo total
    UPDATE education.enrollments
    SET total_time_spent_minutes = (
        SELECT COALESCE(SUM(time_spent_minutes), 0)
        FROM education.lesson_progress
        WHERE enrollment_id = NEW.enrollment_id
    ),
    last_activity_at = NOW(),
    last_lesson_id = NEW.lesson_id,
    last_position_seconds = NEW.video_position_seconds
    WHERE id = NEW.enrollment_id;

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS lesson_progress_enrollment_update ON education.lesson_progress;
CREATE TRIGGER lesson_progress_enrollment_update
    AFTER INSERT OR UPDATE OF is_completed, time_spent_minutes ON education.lesson_progress
    FOR EACH ROW
    EXECUTE FUNCTION education.recalculate_enrollment_on_lesson();

-- Funcion para registrar actividad en leccion
CREATE OR REPLACE FUNCTION education.record_lesson_activity(
    p_enrollment_id UUID,
    p_lesson_id UUID,
    p_video_position INTEGER DEFAULT NULL,
    p_time_spent_minutes INTEGER DEFAULT 0
)
RETURNS UUID AS $$
DECLARE
    v_progress_id UUID;
    v_user_id UUID;
    v_tenant_id UUID;
    v_lesson RECORD;
BEGIN
    -- Obtener datos del enrollment
    SELECT user_id, tenant_id INTO v_user_id, v_tenant_id
    FROM education.enrollments
    WHERE id = p_enrollment_id;

    -- Obtener datos de la leccion
    SELECT * INTO v_lesson
    FROM education.lessons
    WHERE id = p_lesson_id;

    -- Insertar o actualizar progreso
    INSERT INTO education.lesson_progress (
        enrollment_id, lesson_id, user_id, tenant_id,
        is_started, video_position_seconds, time_spent_minutes,
        last_accessed_at
    ) VALUES (
        p_enrollment_id, p_lesson_id, v_user_id, v_tenant_id,
        TRUE, COALESCE(p_video_position, 0), p_time_spent_minutes,
        NOW()
    )
    ON CONFLICT (enrollment_id, lesson_id)
    DO UPDATE SET
        video_position_seconds = COALESCE(p_video_position, education.lesson_progress.video_position_seconds),
        time_spent_minutes = education.lesson_progress.time_spent_minutes + p_time_spent_minutes,
        visit_count = education.lesson_progress.visit_count + 1,
        last_accessed_at = NOW()
    RETURNING id INTO v_progress_id;

    -- Verificar si se completo el video
    IF p_video_position IS NOT NULL AND v_lesson.video_duration_seconds IS NOT NULL THEN
        IF p_video_position >= (v_lesson.video_duration_seconds * 0.9) THEN
            UPDATE education.lesson_progress
            SET video_completed = TRUE,
                video_progress_percent = 100,
                is_completed = CASE WHEN NOT v_lesson.has_quiz THEN TRUE ELSE is_completed END
            WHERE id = v_progress_id;
        ELSE
            UPDATE education.lesson_progress
            SET video_progress_percent = (p_video_position::DECIMAL / v_lesson.video_duration_seconds * 100)
            WHERE id = v_progress_id;
        END IF;
    END IF;

    RETURN v_progress_id;
END;
$$ LANGUAGE plpgsql;

-- Vista de progreso detallado de un enrollment
CREATE OR REPLACE VIEW education.v_enrollment_progress AS
SELECT
    lp.enrollment_id,
    lp.lesson_id,
    l.title AS lesson_title,
    l.content_type,
    l.sequence_number,
    m.id AS module_id,
    m.title AS module_title,
    m.sequence_number AS module_sequence,
    lp.is_started,
    lp.is_completed,
    lp.video_progress_percent,
    lp.time_spent_minutes,
    lp.quiz_passed,
    lp.completed_at
FROM education.lesson_progress lp
JOIN education.lessons l ON lp.lesson_id = l.id
JOIN education.modules m ON l.module_id = m.id
ORDER BY m.sequence_number, l.sequence_number;

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

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

CREATE POLICY lesson_progress_user_isolation ON education.lesson_progress
    FOR SELECT
    USING (user_id = current_setting('app.current_user_id', true)::UUID);

-- Grants
GRANT SELECT, INSERT, UPDATE ON education.lesson_progress TO trading_app;
GRANT SELECT ON education.lesson_progress TO trading_readonly;
GRANT SELECT ON education.v_enrollment_progress TO trading_app;
GRANT EXECUTE ON FUNCTION education.record_lesson_activity TO trading_app;
