-- name: GetCoursesWithHierarchy :many
SELECT
    cc.id AS category_id,
    cc.name AS category_name,
    csc.id AS sub_category_id,
    csc.name AS sub_category_name,
    c.id AS course_id,
    c.title AS course_title
FROM course_categories cc
LEFT JOIN course_sub_categories csc ON csc.category_id = cc.id AND csc.is_active = TRUE
LEFT JOIN courses c ON c.sub_category_id = csc.id AND c.is_active = TRUE
WHERE cc.is_active = TRUE
ORDER BY cc.id, csc.display_order, csc.id, c.id;

-- name: GetLevelsByCourseID :many
SELECT *
FROM levels
WHERE course_id = $1
  AND is_active = TRUE
ORDER BY display_order ASC, id ASC;

-- name: GetAllLevels :many
SELECT
    COUNT(*) OVER () AS total_count,
    l.*
FROM levels l
ORDER BY l.display_order ASC, l.id ASC
LIMIT sqlc.narg('limit')::INT
OFFSET sqlc.narg('offset')::INT;

-- name: GetLevelByID :one
SELECT *
FROM levels
WHERE id = $1;

-- name: GetModulesByLevelID :many
SELECT *
FROM modules
WHERE level_id = $1
  AND is_active = TRUE
ORDER BY display_order ASC, id ASC;

-- name: GetAllModules :many
SELECT
    COUNT(*) OVER () AS total_count,
    m.*
FROM modules m
ORDER BY m.display_order ASC, m.id ASC
LIMIT sqlc.narg('limit')::INT
OFFSET sqlc.narg('offset')::INT;

-- name: GetModuleByID :one
SELECT *
FROM modules
WHERE id = $1;

-- name: GetSubModulesByModuleID :many
SELECT *
FROM sub_modules
WHERE module_id = $1
  AND is_active = TRUE
ORDER BY display_order ASC, id ASC;

-- name: GetAllSubModules :many
SELECT
    COUNT(*) OVER () AS total_count,
    sm.*
FROM sub_modules sm
ORDER BY sm.display_order ASC, sm.id ASC
LIMIT sqlc.narg('limit')::INT
OFFSET sqlc.narg('offset')::INT;

-- name: GetSubModuleByID :one
SELECT *
FROM sub_modules
WHERE id = $1;

-- name: GetSubModuleVideos :many
SELECT *
FROM sub_module_videos
WHERE sub_module_id = $1
  AND status != 'ARCHIVED'
ORDER BY display_order ASC, id ASC;

-- name: GetSubModuleLessons :many
SELECT *
FROM sub_module_lessons
WHERE sub_module_id = $1
  AND is_active = TRUE
ORDER BY display_order ASC, id ASC;

-- name: GetSubModuleLessonsAll :many
SELECT *
FROM sub_module_lessons
WHERE sub_module_id = $1
ORDER BY display_order ASC, id ASC;

-- name: GetSubModuleLessonByID :one
SELECT *
FROM sub_module_lessons
WHERE id = $1;

-- name: GetSubModulePractices :many
SELECT
    smp.id,
    smp.sub_module_id,
    smp.title,
    smp.description,
    smp.thumbnail,
    smp.intro_video_url,
    smp.question_set_id,
    smp.display_order,
    smp.is_active,
    smp.inactive_since,
    qs.status,
    qs.set_type,
    (SELECT COUNT(*) FROM question_set_items qsi WHERE qsi.set_id = qs.id) AS question_count
FROM sub_module_practices smp
JOIN question_sets qs ON qs.id = smp.question_set_id
WHERE smp.sub_module_id = $1
  AND smp.is_active = TRUE
  AND qs.set_type = 'PRACTICE'
ORDER BY smp.display_order ASC, smp.id ASC;

-- name: GetSubModulePracticeByID :one
SELECT
    smp.id,
    smp.sub_module_id,
    smp.title,
    smp.description,
    smp.thumbnail,
    smp.intro_video_url,
    smp.question_set_id,
    smp.display_order,
    smp.is_active,
    smp.inactive_since,
    qs.status,
    qs.set_type,
    (SELECT COUNT(*) FROM question_set_items qsi WHERE qsi.set_id = qs.id) AS question_count
FROM sub_module_practices smp
JOIN question_sets qs ON qs.id = smp.question_set_id
WHERE smp.id = $1
  AND smp.is_active = TRUE
  AND qs.set_type = 'PRACTICE';

-- name: GetSubModuleCapstones :many
SELECT
    smc.id,
    smc.sub_module_id,
    smc.title,
    smc.description,
    smc.tips,
    smc.thumbnail,
    smc.question_set_id,
    smc.display_order,
    smc.is_active,
    smc.inactive_since,
    qs.status,
    qs.set_type,
    qs.time_limit_minutes,
    qs.passing_score,
    qs.shuffle_questions,
    (SELECT COUNT(*) FROM question_set_items qsi WHERE qsi.set_id = qs.id) AS question_count
FROM sub_module_capstones smc
JOIN question_sets qs ON qs.id = smc.question_set_id
WHERE smc.sub_module_id = $1
  AND smc.is_active = TRUE
  AND qs.set_type = 'CAPSTONE'
ORDER BY smc.display_order ASC, smc.id ASC;

-- name: GetSubModuleCapstoneByID :one
SELECT
    smc.id,
    smc.sub_module_id,
    smc.title,
    smc.description,
    smc.tips,
    smc.thumbnail,
    smc.question_set_id,
    smc.display_order,
    smc.is_active,
    smc.inactive_since,
    qs.status,
    qs.set_type,
    qs.time_limit_minutes,
    qs.passing_score,
    qs.shuffle_questions,
    (SELECT COUNT(*) FROM question_set_items qsi WHERE qsi.set_id = qs.id) AS question_count
FROM sub_module_capstones smc
JOIN question_sets qs ON qs.id = smc.question_set_id
WHERE smc.id = $1
  AND smc.is_active = TRUE
  AND qs.set_type = 'CAPSTONE';

-- name: GetFullHierarchyByCourseID :many
SELECT
    c.id AS course_id,
    c.title AS course_title,
    l.id AS level_id,
    l.cefr_level,
    l.title AS level_title,
    l.description AS level_description,
    l.thumbnail AS level_thumbnail,
    m.id AS module_id,
    m.title AS module_title,
    m.icon_url AS module_icon_url,
    sm.id AS sub_module_id,
    sm.title AS sub_module_title,
    sm.description AS sub_module_description,
    sm.thumbnail AS sub_module_thumbnail,
    sm.tips AS sub_module_tips,
    sm.display_order AS sub_module_display_order
FROM courses c
LEFT JOIN levels l ON l.course_id = c.id AND l.is_active = TRUE
LEFT JOIN modules m ON m.level_id = l.id AND m.is_active = TRUE
LEFT JOIN sub_modules sm ON sm.module_id = m.id AND sm.is_active = TRUE
WHERE c.id = $1
ORDER BY l.display_order, l.id, m.display_order, m.id, sm.display_order, sm.id;

-- name: CreateCourseSubCategory :one
INSERT INTO course_sub_categories (
    category_id,
    name,
    description,
    display_order,
    is_active
)
VALUES ($1, $2, $3, COALESCE($4, 0), COALESCE($5, TRUE))
RETURNING *;

-- name: GetCourseSubCategories :many
SELECT
    COUNT(*) OVER () AS total_count,
    csc.id,
    csc.category_id,
    cc.name AS category_name,
    csc.name,
    csc.description,
    csc.display_order,
    csc.is_active,
    csc.created_at
FROM course_sub_categories csc
JOIN course_categories cc ON cc.id = csc.category_id
WHERE csc.is_active = TRUE
ORDER BY csc.display_order ASC, csc.id ASC
LIMIT sqlc.narg('limit')::INT
OFFSET sqlc.narg('offset')::INT;

-- name: GetCourseSubCategoriesByCategoryID :many
SELECT
    COUNT(*) OVER () AS total_count,
    csc.id,
    csc.category_id,
    cc.name AS category_name,
    csc.name,
    csc.description,
    csc.display_order,
    csc.is_active,
    csc.created_at
FROM course_sub_categories csc
JOIN course_categories cc ON cc.id = csc.category_id
WHERE csc.category_id = $1
  AND csc.is_active = TRUE
ORDER BY csc.display_order ASC, csc.id ASC
LIMIT sqlc.narg('limit')::INT
OFFSET sqlc.narg('offset')::INT;

-- name: GetHumanLanguageCourseSubCategories :many
SELECT
    COUNT(*) OVER () AS total_count,
    csc.id,
    csc.category_id,
    cc.name AS category_name,
    csc.name,
    csc.description,
    csc.display_order,
    csc.is_active,
    csc.created_at
FROM course_sub_categories csc
JOIN course_categories cc ON cc.id = csc.category_id
WHERE csc.is_active = TRUE
  AND cc.is_active = TRUE
  AND lower(trim(cc.name)) = 'human language'
ORDER BY csc.display_order ASC, csc.id ASC
LIMIT sqlc.narg('limit')::INT
OFFSET sqlc.narg('offset')::INT;

-- name: CreateLevel :one
INSERT INTO levels (
    course_id,
    cefr_level,
    title,
    description,
    thumbnail,
    display_order,
    is_active
)
VALUES ($1, $2, $3, $4, $5, COALESCE($6, 0), COALESCE($7, TRUE))
RETURNING *;

-- name: UpdateLevel :one
UPDATE levels
SET
    title = $1,
    description = $2,
    thumbnail = $3,
    display_order = $4,
    is_active = $5
WHERE id = $6
RETURNING *;

-- name: CreateModule :one
INSERT INTO modules (
    level_id,
    title,
    description,
    icon_url,
    display_order,
    is_active
)
VALUES ($1, $2, $3, $4, COALESCE($5, 0), COALESCE($6, TRUE))
RETURNING *;

-- name: UpdateModule :one
UPDATE modules
SET
    title = $1,
    description = $2,
    icon_url = $3,
    display_order = $4,
    is_active = $5
WHERE id = $6
RETURNING *;

-- name: CreateSubModule :one
INSERT INTO sub_modules (
    module_id,
    title,
    description,
    thumbnail,
    tips,
    display_order,
    is_active
)
VALUES ($1, $2, $3, $4, $5, COALESCE($6, 0), COALESCE($7, TRUE))
RETURNING *;

-- name: UpdateSubModule :one
UPDATE sub_modules
SET
    title = $1,
    description = $2,
    thumbnail = $3,
    tips = $4,
    display_order = $5,
    is_active = $6
WHERE id = $7
RETURNING *;

-- name: CreateSubModuleVideo :one
INSERT INTO sub_module_videos (
    sub_module_id,
    title,
    description,
    video_url,
    duration,
    resolution,
    is_published,
    publish_date,
    visibility,
    instructor_id,
    thumbnail,
    display_order,
    status,
    vimeo_id,
    vimeo_embed_url,
    vimeo_player_html,
    vimeo_status,
    video_host_provider
)
VALUES (
    $1, $2, $3, $4, $5, $6,
    COALESCE($7, FALSE), $8, $9, $10, $11,
    COALESCE($12, 0), COALESCE($13, 'DRAFT'),
    $14, $15, $16, $17, COALESCE($18, 'DIRECT')
)
RETURNING *;

-- name: CreateSubModuleLesson :one
INSERT INTO sub_module_lessons (
    sub_module_id,
    title,
    description,
    thumbnail,
    teaching_text,
    teaching_image_url,
    teaching_audio_url,
    teaching_video_url,
    display_order,
    is_active,
    inactive_since
)
VALUES (
    $1,
    $2,
    $3,
    $4,
    $5,
    $6,
    $7,
    $8,
    COALESCE($9, 0),
    COALESCE($10, TRUE),
    CASE WHEN COALESCE($10, TRUE) THEN NULL ELSE NOW() END
)
RETURNING *;

-- name: UpdateSubModuleLesson :one
UPDATE sub_module_lessons
SET
    sub_module_id = $1,
    title = $2,
    description = $3,
    thumbnail = $4,
    teaching_text = $5,
    teaching_image_url = $6,
    teaching_audio_url = $7,
    teaching_video_url = $8,
    display_order = $9,
    is_active = $10,
    inactive_since = CASE
        WHEN $10 THEN NULL
        WHEN is_active THEN NOW()
        ELSE inactive_since
    END
WHERE id = $11
RETURNING *;

-- name: CreateSubModulePractice :one
INSERT INTO sub_module_practices (
    sub_module_id,
    title,
    description,
    thumbnail,
    intro_video_url,
    question_set_id,
    display_order,
    is_active,
    inactive_since
)
VALUES ($1, $2, $3, $4, $5, $6, COALESCE($7, 0), COALESCE($8, TRUE), CASE WHEN COALESCE($8, TRUE) THEN NULL ELSE NOW() END)
RETURNING *;

-- name: CreateSubModuleCapstone :one
INSERT INTO sub_module_capstones (
    sub_module_id,
    title,
    description,
    tips,
    thumbnail,
    question_set_id,
    display_order,
    is_active,
    inactive_since
)
VALUES ($1, $2, $3, $4, $5, $6, COALESCE($7, 0), COALESCE($8, TRUE), CASE WHEN COALESCE($8, TRUE) THEN NULL ELSE NOW() END)
RETURNING *;

-- name: UpdateSubModuleCapstone :one
UPDATE sub_module_capstones
SET
    title = $1,
    description = $2,
    tips = $3,
    thumbnail = $4,
    display_order = $5,
    is_active = $6,
    inactive_since = CASE
        WHEN $6 THEN NULL
        WHEN is_active THEN NOW()
        ELSE inactive_since
    END
WHERE id = $7
RETURNING *;

-- name: PurgeInactiveSubModuleLessonsBefore :execrows
DELETE FROM sub_module_lessons
WHERE is_active = FALSE
  AND inactive_since IS NOT NULL
  AND inactive_since < $1;

-- name: PurgeInactiveSubModulePracticesBefore :execrows
DELETE FROM question_sets qs
USING (
    SELECT question_set_id
    FROM sub_module_practices
    WHERE is_active = FALSE
      AND inactive_since IS NOT NULL
      AND inactive_since < $1
) doomed
WHERE qs.id = doomed.question_set_id;

-- name: PurgeInactiveSubModuleCapstonesBefore :execrows
DELETE FROM question_sets qs
USING (
    SELECT question_set_id
    FROM sub_module_capstones
    WHERE is_active = FALSE
      AND inactive_since IS NOT NULL
      AND inactive_since < $1
) doomed
WHERE qs.id = doomed.question_set_id;

-- name: GetModuleCapstones :many
SELECT
    mc.id,
    mc.module_id,
    mc.title,
    mc.description,
    mc.tips,
    mc.thumbnail,
    mc.question_set_id,
    mc.display_order,
    mc.is_active,
    qs.status,
    qs.set_type,
    qs.time_limit_minutes,
    qs.passing_score,
    qs.shuffle_questions,
    (SELECT COUNT(*) FROM question_set_items qsi WHERE qsi.set_id = qs.id) AS question_count
FROM module_capstones mc
JOIN question_sets qs ON qs.id = mc.question_set_id
WHERE mc.module_id = $1
  AND mc.is_active = TRUE
  AND qs.set_type = 'CAPSTONE'
ORDER BY mc.display_order ASC, mc.id ASC;

-- name: GetModuleCapstoneByID :one
SELECT
    mc.id,
    mc.module_id,
    mc.title,
    mc.description,
    mc.tips,
    mc.thumbnail,
    mc.question_set_id,
    mc.display_order,
    mc.is_active,
    qs.status,
    qs.set_type,
    qs.time_limit_minutes,
    qs.passing_score,
    qs.shuffle_questions,
    (SELECT COUNT(*) FROM question_set_items qsi WHERE qsi.set_id = qs.id) AS question_count
FROM module_capstones mc
JOIN question_sets qs ON qs.id = mc.question_set_id
WHERE mc.id = $1
  AND mc.is_active = TRUE
  AND qs.set_type = 'CAPSTONE';

-- name: CreateModuleCapstone :one
INSERT INTO module_capstones (
    module_id,
    title,
    description,
    tips,
    thumbnail,
    question_set_id,
    display_order,
    is_active
)
VALUES ($1, $2, $3, $4, $5, $6, COALESCE($7, 0), COALESCE($8, TRUE))
RETURNING *;

-- name: UpdateModuleCapstone :one
UPDATE module_capstones
SET
    title = $1,
    description = $2,
    tips = $3,
    thumbnail = $4,
    display_order = $5,
    is_active = $6
WHERE id = $7
RETURNING *;

