-- ============================================================================
-- VIEW : playlist_videos
-- ============================================================================
DROP VIEW IF EXISTS playlist_videos;

CREATE VIEW playlist_videos AS
WITH
-- 1️⃣ Playlists manuelles
manual_playlists_videos AS (
  SELECT
    p.id AS playlist_id,
    p.name AS playlist_name,
    'manual' AS playlist_type,
    vp.video_file_name
  FROM playlists p
  JOIN video_playlists vp ON p.id = vp.playlist_id
  WHERE p.type = 'manual'
),

-- 2️⃣ Dynamiques sans include/exclude
dynamic_playlist_videos_base AS (
  SELECT DISTINCT
    p.id AS playlist_id,
    p.name AS playlist_name,
    'dynamic' AS playlist_type,
    v.file_name AS video_file_name
  FROM playlists p
  JOIN videos v
  WHERE p.type = 'dynamic'
    -- Labels inclus (AND/OR)
    AND (
      json_array_length(json_extract(p.rules_json, '$.include_labels')) = 0
      OR (
        json_extract(p.rules_json, '$.label_logic') = 'OR'
        AND EXISTS (
          SELECT 1 FROM json_each(json_extract(p.rules_json, '$.include_labels')) jl
          JOIN labels l ON l.name = jl.value
          JOIN video_labels vl ON vl.label_id = l.id AND vl.video_file_name = v.file_name
        )
      )
      OR (
        json_extract(p.rules_json, '$.label_logic') = 'AND'
        AND NOT EXISTS (
          SELECT 1
          FROM json_each(json_extract(p.rules_json, '$.include_labels')) jl
          WHERE jl.value NOT IN (
            SELECT l2.name
            FROM labels l2
            JOIN video_labels vl2 ON l2.id = vl2.label_id
            WHERE vl2.video_file_name = v.file_name
          )
        )
      )
    )
    -- Labels exclus
    AND NOT EXISTS (
      SELECT 1 FROM json_each(json_extract(p.rules_json, '$.exclude_labels')) je
      JOIN labels lx ON lx.name = je.value
      JOIN video_labels vlx ON vlx.label_id = lx.id AND vlx.video_file_name = v.file_name
    )
    -- Dates
    AND (
      json_extract(p.rules_json, '$.date_after') IS NULL
      OR v.record_datetime >= json_extract(p.rules_json, '$.date_after')
      OR (
        json_extract(p.rules_json, '$.date_delta_days') IS NOT NULL
        AND v.record_datetime >= date('now', (json_extract(p.rules_json, '$.date_delta_days') || ' days'))
      )
    )
    AND (
      json_extract(p.rules_json, '$.date_before') IS NULL
      OR v.record_datetime <= json_extract(p.rules_json, '$.date_before')
    )
    -- Difficulty / day / address
    AND (
      json_extract(p.rules_json, '$.difficulty') IS NULL
      OR v.difficulty_level = json_extract(p.rules_json, '$.difficulty')
    )
    AND (
      json_extract(p.rules_json, '$.day_of_week') IS NULL
      OR v.day_of_week = json_extract(p.rules_json, '$.day_of_week')
    )
    AND (
      json_extract(p.rules_json, '$.address_keyword') IS NULL
      OR (
        v.address NOT LIKE '%unknown%'
        AND v.address LIKE '%' || json_extract(p.rules_json, '$.address_keyword') || '%'
      )
    )
),

-- 3️⃣ Inclusions directes (parent → enfant)
playlist_direct_includes AS (
  SELECT
    p.id AS parent_playlist_id,
    CAST(inc.value AS INTEGER) AS child_playlist_id
  FROM playlists p
  JOIN json_each(json_extract(p.rules_json, '$.include_playlists')) inc
    ON json_type(inc.value) IN ('integer', 'text')
  WHERE json_array_length(json_extract(p.rules_json, '$.include_playlists')) > 0
),

-- 4️⃣ Récursion : parent → descendant (transitif)
playlist_includes_recursive AS (
  WITH RECURSIVE rec(parent_playlist_id, child_playlist_id) AS (
    SELECT parent_playlist_id, child_playlist_id FROM playlist_direct_includes
    UNION ALL
    SELECT d.parent_playlist_id, di.child_playlist_id
    FROM playlist_direct_includes d
    JOIN rec di ON di.parent_playlist_id = d.child_playlist_id
  )
  SELECT DISTINCT parent_playlist_id AS parent_id, child_playlist_id AS child_id FROM rec
),

-- 5️⃣ Exclusions directes et récursives
playlist_direct_excludes AS (
  SELECT
    p.id AS parent_playlist_id,
    CAST(exc.value AS INTEGER) AS child_playlist_id
  FROM playlists p
  JOIN json_each(json_extract(p.rules_json, '$.exclude_playlists')) exc
    ON json_type(exc.value) IN ('integer', 'text')
  WHERE json_array_length(json_extract(p.rules_json, '$.exclude_playlists')) > 0
),
playlist_excludes_recursive AS (
  WITH RECURSIVE rec_ex(parent_playlist_id, child_playlist_id) AS (
    SELECT parent_playlist_id, child_playlist_id FROM playlist_direct_excludes
    UNION ALL
    SELECT d.parent_playlist_id, di.child_playlist_id
    FROM playlist_direct_excludes d
    JOIN rec_ex di ON di.parent_playlist_id = d.child_playlist_id
  )
  SELECT DISTINCT parent_playlist_id AS parent_id, child_playlist_id AS child_id FROM rec_ex
),

-- 6️⃣ Vidéos issues des playlists incluses
playlist_included_videos AS (
  SELECT pir.parent_id AS parent_playlist_id, mpv.video_file_name
  FROM playlist_includes_recursive pir
  JOIN manual_playlists_videos mpv ON mpv.playlist_id = pir.child_id
  UNION
  SELECT pir.parent_id AS parent_playlist_id, dpb.video_file_name
  FROM playlist_includes_recursive pir
  JOIN dynamic_playlist_videos_base dpb ON dpb.playlist_id = pir.child_id
),

-- 7️⃣ Inclusion logique OR
playlist_includes_union AS (
  SELECT DISTINCT db.playlist_id, db.playlist_name, db.playlist_type, db.video_file_name
  FROM dynamic_playlist_videos_base db
  JOIN playlists p ON p.id = db.playlist_id
  WHERE json_extract(p.rules_json, '$.logic') = 'OR'
  UNION
  SELECT DISTINCT iv.parent_playlist_id AS playlist_id,
         (SELECT name FROM playlists WHERE id = iv.parent_playlist_id) AS playlist_name,
         'dynamic' AS playlist_type,
         iv.video_file_name
  FROM playlist_included_videos iv
  JOIN playlists p ON p.id = iv.parent_playlist_id
  WHERE json_extract(p.rules_json, '$.logic') = 'OR'
),

-- 8️⃣ Inclusion logique AND (+ fallback si 0 include)
playlist_includes_intersection AS (
  SELECT DISTINCT db.playlist_id, db.playlist_name, db.playlist_type, db.video_file_name
  FROM dynamic_playlist_videos_base db
  JOIN playlists p ON p.id = db.playlist_id
  WHERE json_extract(p.rules_json, '$.logic') = 'AND'
    AND json_array_length(json_extract(p.rules_json, '$.include_playlists')) > 0
    AND db.video_file_name IN (
      SELECT iv.video_file_name
      FROM playlist_included_videos iv
      WHERE iv.parent_playlist_id = db.playlist_id
    )
  UNION ALL
  SELECT DISTINCT db.playlist_id, db.playlist_name, db.playlist_type, db.video_file_name
  FROM dynamic_playlist_videos_base db
  JOIN playlists p ON p.id = db.playlist_id
  WHERE json_extract(p.rules_json, '$.logic') = 'AND'
    AND (
      json_array_length(json_extract(p.rules_json, '$.include_playlists')) IS NULL
      OR json_array_length(json_extract(p.rules_json, '$.include_playlists')) = 0
    )
),

-- 9️⃣ Fusion des deux logiques d’inclusion
playlist_after_includes AS (
  SELECT * FROM playlist_includes_union
  UNION ALL
  SELECT * FROM playlist_includes_intersection
),

-- 🔟 Vidéos exclues (via exclude_playlists récursif)
playlist_excluded_videos AS (
  SELECT per.parent_id AS parent_playlist_id, mpv.video_file_name
  FROM playlist_excludes_recursive per
  JOIN manual_playlists_videos mpv ON mpv.playlist_id = per.child_id
  UNION
  SELECT per.parent_id AS parent_playlist_id, dpb.video_file_name
  FROM playlist_excludes_recursive per
  JOIN dynamic_playlist_videos_base dpb ON dpb.playlist_id = per.child_id
),

-- 1️⃣1️⃣ Application des exclusions
playlist_after_excludes AS (
  SELECT pai.playlist_id, pai.playlist_name, pai.playlist_type, pai.video_file_name
  FROM playlist_after_includes pai
  LEFT JOIN playlist_excluded_videos pev
    ON pev.parent_playlist_id = pai.playlist_id AND pev.video_file_name = pai.video_file_name
  WHERE pev.parent_playlist_id IS NULL
)

-- 1️⃣2️⃣ Résultat final : union manuelles + dynamiques
SELECT playlist_id, playlist_name, playlist_type, video_file_name
FROM manual_playlists_videos
UNION ALL
SELECT playlist_id, playlist_name, playlist_type, video_file_name
FROM playlist_after_excludes;


-- ============================================================================
-- TABLE AGRÉGÉE : video_summary
-- ============================================================================
DROP VIEW IF EXISTS video_summary;

CREATE VIEW video_summary AS
SELECT
  v.file_name,
  v.raw_file,
  v.mp4_file,
  v.record_datetime,
  v.day_of_week,
  v.difficulty_level,
  v.address,
  GROUP_CONCAT(DISTINCT l.name) AS labels,
  GROUP_CONCAT(DISTINCT pv.playlist_name) AS playlists
FROM videos v
LEFT JOIN video_labels vl ON vl.video_file_name = v.file_name
LEFT JOIN labels l ON l.id = vl.label_id
LEFT JOIN playlist_videos pv ON pv.video_file_name = v.file_name
GROUP BY v.file_name;

CREATE TABLE IF NOT EXISTS video_summary_materialized AS
SELECT * FROM video_summary;