-- Extension du schéma DanceVideos/ pour le projet video_analysis/
-- Voir adr/0004-db-extension-strategy.md
-- Convention héritée de DanceVideos : la PK de `videos` est `file_name VARCHAR(255)`,
-- les tables filles utilisent `video_file_name VARCHAR(255)` comme FK.

PRAGMA foreign_keys = ON;

-- Groupes de vidéos d'un même cours (V0.6, voir adr/0010)
CREATE TABLE IF NOT EXISTS video_groups (
  id                INTEGER PRIMARY KEY AUTOINCREMENT,
  label             TEXT,
  time_start        DATETIME,
  time_end          DATETIME,
  n_videos          INTEGER,
  style             TEXT,
  pipeline_version  TEXT NOT NULL,
  notes             TEXT
);

CREATE TABLE IF NOT EXISTS video_group_members (
  video_file_name   VARCHAR(255) PRIMARY KEY,
  group_id          INTEGER NOT NULL,
  role              TEXT CHECK (role IN ('explicative', 'demonstration', 'mixte', 'unknown')),
  seq_idx           INTEGER,
  FOREIGN KEY (video_file_name) REFERENCES videos(file_name) ON DELETE CASCADE,
  FOREIGN KEY (group_id) REFERENCES video_groups(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_vgm_group ON video_group_members(group_id);

-- Une analyse par version de pipeline et par vidéo
CREATE TABLE IF NOT EXISTS analyses (
  id               INTEGER PRIMARY KEY AUTOINCREMENT,
  video_file_name  VARCHAR(255) NOT NULL,
  niveau           TEXT NOT NULL,            -- "audio_demix" | "beats" | "asr" | "pose" | "segment" | "label"
  pipeline_version TEXT NOT NULL,
  started_at       DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  finished_at      DATETIME,
  summary_json     TEXT,
  FOREIGN KEY (video_file_name) REFERENCES videos(file_name) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_analyses_video ON analyses(video_file_name, niveau);

-- Segmentation audio (parole / musique / silence / mixed)
CREATE TABLE IF NOT EXISTS audio_segments (
  id              INTEGER PRIMARY KEY AUTOINCREMENT,
  video_file_name VARCHAR(255) NOT NULL,
  start_s         REAL NOT NULL,
  end_s           REAL NOT NULL,
  kind            TEXT NOT NULL CHECK (kind IN ('parole', 'musique', 'silence', 'mixed')),
  speaker_id      TEXT,
  text            TEXT,
  confidence      REAL,
  FOREIGN KEY (video_file_name) REFERENCES videos(file_name) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_audio_segments_video ON audio_segments(video_file_name, start_s);

-- Beats / downbeats / tempo
CREATE TABLE IF NOT EXISTS beats (
  id              INTEGER PRIMARY KEY AUTOINCREMENT,
  video_file_name VARCHAR(255) NOT NULL,
  t_s             REAL NOT NULL,
  beat_in_bar     INTEGER NOT NULL,         -- 1..4 typiquement
  is_downbeat     BOOLEAN NOT NULL,
  bpm             REAL,
  FOREIGN KEY (video_file_name) REFERENCES videos(file_name) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_beats_video ON beats(video_file_name, t_s);

-- Régimes intra-vidéo (avec_compte / en_musique / mixte / explication / silence) — voir adr/0009
CREATE TABLE IF NOT EXISTS regime_segments (
  id                INTEGER PRIMARY KEY AUTOINCREMENT,
  video_file_name   VARCHAR(255) NOT NULL,
  start_s           REAL NOT NULL,
  end_s             REAL NOT NULL,
  regime            TEXT NOT NULL CHECK (regime IN ('avec_compte', 'en_musique', 'mixte', 'explication', 'compte_avec_explication', 'silence')),
  confidence        REAL,
  pipeline_version  TEXT NOT NULL,
  FOREIGN KEY (video_file_name) REFERENCES videos(file_name) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_regime_video_t ON regime_segments(video_file_name, start_s);

-- Transcription word-level (WhisperX) — voir adr/0008
CREATE TABLE IF NOT EXISTS transcription_words (
  id                INTEGER PRIMARY KEY AUTOINCREMENT,
  video_file_name   VARCHAR(255) NOT NULL,
  audio_segment_id  INTEGER,
  t_start_s         REAL NOT NULL,
  t_end_s           REAL NOT NULL,
  word              TEXT NOT NULL,
  speaker_id        TEXT,
  confidence        REAL,
  pipeline_version  TEXT NOT NULL,
  FOREIGN KEY (video_file_name) REFERENCES videos(file_name) ON DELETE CASCADE,
  FOREIGN KEY (audio_segment_id) REFERENCES audio_segments(id) ON DELETE SET NULL
);
CREATE INDEX IF NOT EXISTS idx_words_video_t ON transcription_words(video_file_name, t_start_s);
CREATE INDEX IF NOT EXISTS idx_words_text ON transcription_words(word);

-- Labels sémantiques attachés aux dance_segments depuis l'ASR (V0.5.4)
CREATE TABLE IF NOT EXISTS dance_segment_labels (
  id                INTEGER PRIMARY KEY AUTOINCREMENT,
  segment_id        TEXT NOT NULL,
  label             TEXT NOT NULL,
  category          TEXT,                  -- "body_part" | "movement" | "direction" | "figure" | "rhythm"
  source            TEXT NOT NULL CHECK (source IN ('asr-keyword', 'asr-figure', 'user', 'manual')),
  t_offset_s        REAL,                  -- décalage du keyword par rapport au début du segment (négatif = avant)
  confidence        REAL,
  pipeline_version  TEXT NOT NULL,
  FOREIGN KEY (segment_id) REFERENCES dance_segments(segment_id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_dsl_segment ON dance_segment_labels(segment_id);
CREATE INDEX IF NOT EXISTS idx_dsl_label ON dance_segment_labels(label);

-- Personnes détectées dans la vidéo (prof, partenaire, audience)
CREATE TABLE IF NOT EXISTS persons (
  id              INTEGER PRIMARY KEY AUTOINCREMENT,
  video_file_name VARCHAR(255) NOT NULL,
  person_id       INTEGER NOT NULL,         -- ID stable inter-frames (ByteTrack)
  role            TEXT NOT NULL CHECK (role IN ('prof', 'partner', 'audience', 'unknown')),
  notes           TEXT,
  FOREIGN KEY (video_file_name) REFERENCES videos(file_name) ON DELETE CASCADE,
  UNIQUE (video_file_name, person_id)
);

-- Pose keypoints (frame-decimated, 1/N frame typiquement)
CREATE TABLE IF NOT EXISTS pose_keypoints (
  id              INTEGER PRIMARY KEY AUTOINCREMENT,
  video_file_name VARCHAR(255) NOT NULL,
  frame           INTEGER NOT NULL,
  person_id       INTEGER NOT NULL,
  kp_json         TEXT NOT NULL,            -- JSON compressé : 133 keypoints {x, y, score}
  FOREIGN KEY (video_file_name) REFERENCES videos(file_name) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_pose_kp_video_frame ON pose_keypoints(video_file_name, frame);

-- Segments hiérarchiques de chorégraphie (cœur de l'UX cumulation/réduction)
CREATE TABLE IF NOT EXISTS dance_segments (
  segment_id          TEXT PRIMARY KEY,     -- ex. "v17:meso:0008"
  video_file_name     VARCHAR(255) NOT NULL,
  start_s             REAL NOT NULL,
  end_s               REAL NOT NULL,
  level               TEXT NOT NULL CHECK (level IN ('macro', 'meso', 'micro', 'nano')),
  parent_segment_id   TEXT,
  label               TEXT,
  source              TEXT NOT NULL CHECK (source IN ('auto-rules', 'auto-tcn', 'teacher-said', 'user')),
  confidence          REAL,
  FOREIGN KEY (video_file_name) REFERENCES videos(file_name) ON DELETE CASCADE,
  FOREIGN KEY (parent_segment_id) REFERENCES dance_segments(segment_id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_dance_segments_video ON dance_segments(video_file_name, level, start_s);
CREATE INDEX IF NOT EXISTS idx_dance_segments_parent ON dance_segments(parent_segment_id);

-- Patterns nommés (mise en espagnol, dile que no, pas de bourré...)
CREATE TABLE IF NOT EXISTS patterns (
  id                INTEGER PRIMARY KEY AUTOINCREMENT,
  name              TEXT UNIQUE NOT NULL,
  description       TEXT,
  style             TEXT,                   -- "salsa cubaine" | "bachata" | "common" | ...
  templates_json    TEXT,                    -- liste d'occurrences (video_file_name + segment_id) servant de templates
  occurrences_count INTEGER DEFAULT 0
);

-- Benchmarks — résultats d'évaluation par pipeline_version × méthode × tolérance × vidéo
-- (voir doc/observabilite-backoffice.md § 5, notebooks/02-segmentation-eval)
CREATE TABLE IF NOT EXISTS benchmarks (
  id                INTEGER PRIMARY KEY AUTOINCREMENT,
  pipeline_version  TEXT NOT NULL,            -- ex. "v0.5.0", "v0.5.0-beat_this-raw-audio"
  run_at            DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  notebook          TEXT,                     -- nom/chemin du notebook qui a produit la mesure
  golden_set        TEXT,                     -- ex. "decoupe/diegoRiviera.json" ou "decoupe/all"
  video_file_name   VARCHAR(255),             -- vidéo ; nullable si métrique agrégée
  method            TEXT NOT NULL,            -- "V0_meso" | "4bar_grid" | "uniform_5s" | ...
  tol_s             REAL NOT NULL,            -- tolérance en secondes
  precision_score   REAL NOT NULL,
  recall_score      REAL NOT NULL,
  f1_score          REAL NOT NULL,
  n_pred            INTEGER NOT NULL,
  n_gold            INTEGER NOT NULL,
  notes             TEXT,
  FOREIGN KEY (video_file_name) REFERENCES videos(file_name) ON DELETE SET NULL
);
CREATE INDEX IF NOT EXISTS idx_benchmarks_version ON benchmarks(pipeline_version, method, tol_s);
CREATE INDEX IF NOT EXISTS idx_benchmarks_run ON benchmarks(run_at);

-- Journal d'éditions (audit trail + undo/redo unifiés) — voir adr/0013
CREATE TABLE IF NOT EXISTS edits_journal (
  id              INTEGER PRIMARY KEY AUTOINCREMENT,
  user_id         TEXT NOT NULL DEFAULT 'default',
  video_file_name VARCHAR(255),
  transaction_id  TEXT NOT NULL,
  op_type         TEXT NOT NULL,
  target_table    TEXT NOT NULL,
  target_id       TEXT NOT NULL,
  before_json     TEXT,
  after_json      TEXT,
  created_at      DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  undone_at       DATETIME,
  redone_at       DATETIME,
  pipeline_version TEXT,
  FOREIGN KEY (video_file_name) REFERENCES videos(file_name) ON DELETE SET NULL
);
CREATE INDEX IF NOT EXISTS idx_edits_video_t ON edits_journal(video_file_name, created_at);
CREATE INDEX IF NOT EXISTS idx_edits_txn ON edits_journal(transaction_id);
CREATE INDEX IF NOT EXISTS idx_edits_active ON edits_journal(undone_at, created_at);

-- Handles d'ancrage cross-vidéo (paires _C_/_M_) — voir adr/0014
CREATE TABLE IF NOT EXISTS video_group_handles (
  id              INTEGER PRIMARY KEY AUTOINCREMENT,
  group_id        INTEGER NOT NULL,
  source_video    VARCHAR(255) NOT NULL,
  source_t_s      REAL NOT NULL,
  target_video    VARCHAR(255) NOT NULL,
  target_t_s      REAL NOT NULL,
  label           TEXT,
  created_by      TEXT NOT NULL DEFAULT 'default',
  created_at      DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  notes           TEXT,
  FOREIGN KEY (group_id) REFERENCES video_groups(id) ON DELETE CASCADE,
  FOREIGN KEY (source_video) REFERENCES videos(file_name) ON DELETE CASCADE,
  FOREIGN KEY (target_video) REFERENCES videos(file_name) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_handle_group ON video_group_handles(group_id);
CREATE INDEX IF NOT EXISTS idx_handle_pair ON video_group_handles(source_video, target_video);

-- Prédictions de style par classifieur RF (V0.6.1, voir adr/0011)
CREATE TABLE IF NOT EXISTS style_predictions (
  id              INTEGER PRIMARY KEY AUTOINCREMENT,
  file_name       VARCHAR(255) NOT NULL,
  style           TEXT NOT NULL,
  confidence      REAL,
  model_version   TEXT NOT NULL,
  predicted_at    DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (file_name) REFERENCES videos(file_name) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_stylepred_file ON style_predictions(file_name);
CREATE INDEX IF NOT EXISTS idx_stylepred_style ON style_predictions(style);

-- État de navigation persistant (UX cumulation/réduction)
CREATE TABLE IF NOT EXISTS nav_state (
  id                  INTEGER PRIMARY KEY AUTOINCREMENT,
  video_file_name     VARCHAR(255) NOT NULL,
  user_id             TEXT NOT NULL DEFAULT 'default',
  current_segment_id  TEXT,
  view_level          TEXT CHECK (view_level IN ('macro', 'meso', 'micro', 'nano')),
  updated_at          DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (video_file_name) REFERENCES videos(file_name) ON DELETE CASCADE,
  FOREIGN KEY (current_segment_id) REFERENCES dance_segments(segment_id) ON DELETE SET NULL,
  UNIQUE (video_file_name, user_id)
);

-- Atomes de mouvement (V0.10, voir adr/0018) — granularité beat / demi-beat.
-- Modèle hybride : continu + soft distribution + argmax + confidence.
CREATE TABLE IF NOT EXISTS beat_atoms (
  id                          INTEGER PRIMARY KEY AUTOINCREMENT,
  video_file_name             VARCHAR(255) NOT NULL,
  person_id                   INTEGER NOT NULL DEFAULT 0,
  t_s                         REAL NOT NULL,
  beat_position               REAL NOT NULL,
  is_downbeat                 BOOLEAN NOT NULL,
  -- Pied gauche
  left_foot_height            REAL,
  left_foot_speed             REAL,
  left_foot_stability         REAL,
  left_foot_state             VARCHAR(20),
  left_foot_state_confidence  REAL,
  left_foot_state_dist_json   TEXT,
  -- Pied droit
  right_foot_height           REAL,
  right_foot_speed            REAL,
  right_foot_stability        REAL,
  right_foot_state            VARCHAR(20),
  right_foot_state_confidence REAL,
  right_foot_state_dist_json  TEXT,
  -- Transfert de poids
  weight_ratio                REAL,
  weight_transfer_velocity    REAL,
  weight_on                   VARCHAR(10),
  -- Cinématique bassin (en hip-widths)
  pelvis_x                    REAL,
  pelvis_y                    REAL,
  pelvis_vel_x                REAL,
  pelvis_vel_y                REAL,
  -- Qualité globale
  pose_confidence             REAL NOT NULL,
  pipeline_version            TEXT NOT NULL,
  computed_at                 DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (video_file_name) REFERENCES videos(file_name) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_atom_video_t ON beat_atoms(video_file_name, t_s);
CREATE INDEX IF NOT EXISTS idx_atom_video_beat ON beat_atoms(video_file_name, beat_position);
