-- ============================================================
-- Migration 1.6.0 - Optimisation des temps de reponse
-- ============================================================
-- Cible : MariaDB 10.4+ (XAMPP local).
-- Idempotent : ce fichier peut etre rejoue sans erreur sur n'importe quel poste.
-- Aucun changement de structure : seuls des index sont ajoutes
-- (via une procedure stockee qui teste leur presence) et la vue
-- sessiondebriefs est redefinie via CREATE OR REPLACE VIEW.
-- ============================================================

USE proserveapi;

-- ------------------------------------------------------------
-- Procedure helper : ajoute un index seulement s'il n'existe pas
-- (CREATE INDEX IF NOT EXISTS n'est dispo qu'a partir de MariaDB 10.5.4)
-- ------------------------------------------------------------
DROP PROCEDURE IF EXISTS create_index_if_missing;

DELIMITER $$
CREATE PROCEDURE create_index_if_missing(
    IN p_table VARCHAR(64),
    IN p_index VARCHAR(64),
    IN p_cols  VARCHAR(255)
)
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.STATISTICS
         WHERE TABLE_SCHEMA = DATABASE()
           AND TABLE_NAME   = p_table
           AND INDEX_NAME   = p_index
    ) THEN
        SET @sql = CONCAT('ALTER TABLE `', p_table, '` ADD INDEX `', p_index, '` (', p_cols, ')');
        PREPARE stmt FROM @sql;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    END IF;
END$$
DELIMITER ;

-- ------------------------------------------------------------
-- Index manquants identifies a l'analyse des requetes lourdes
-- ------------------------------------------------------------

-- JOIN reactevents <-> triggerevents : la cle composite la plus utilisee
CALL create_index_if_missing('reactevents',   'idx_react_session_event',  '`srcEventSessionId`, `srcEventIndex`');

-- Filtres "tirs d'un user dans une session" (stats_object getShotsFiredByUser, getTargetKilledInSession)
CALL create_index_if_missing('triggerevents', 'idx_trigger_session_user', '`sessionId`, `srcUserId`');

-- Agregation NbKilled (auto-jointure RK dans la vue sessiondebriefs)
CALL create_index_if_missing('reactevents',   'idx_react_killed',         '`targetKilled`, `srcEventSessionId`');

-- Tri/filtrage des sessions par date (listes recentes)
CALL create_index_if_missing('sessions',      'idx_sessions_date',        '`sessionDate` DESC');

-- Nettoyage de la procedure helper
DROP PROCEDURE create_index_if_missing;


-- ------------------------------------------------------------
-- Redefinition de la vue sessiondebriefs (idempotent via CREATE OR REPLACE)
-- ------------------------------------------------------------
-- Modifications par rapport a la definition d'origine :
--   - Suppression des wraps "(SELECT IFNULL(...))" qui forcaient une evaluation par row
--     -> remplaces par IFNULL(...) directement (semantique identique).
--   - Suppression des sous-requetes correlees (SELECT R.displayName FROM userroles R WHERE R.id = ...)
--     -> remplacees par deux LEFT JOIN explicites sur userroles (URS et URT).
--   - Tous les autres JOIN, le GROUP BY et l'ORDER BY restent strictement identiques
--     pour preserver le contrat de sortie (memes colonnes, memes lignes, memes valeurs).
-- ------------------------------------------------------------

CREATE OR REPLACE VIEW sessiondebriefs AS
SELECT
    S.id              AS SessionId,
    S.sessionType     AS SessionTypeId,
    ST.displayName    AS SessionType,
    S.sessionName     AS SessionName,
    S.sessionDate     AS SessionDate,
    S.mapName         AS MapName,
    S.scenarioName    AS ScenarioName,
    S.success         AS SessionSuccessful,
    S.timeToFinish    AS SessionDuration,
    COALESCE(T.type, -1)              AS TriggerTypeId,
    COALESCE(TT.displayName, '')      AS TriggerType,
    IFNULL(T.srcUserId, PS.userId)    AS ShooterId,
    US.username                       AS ShooterName,
    IFNULL(PS.role, 3)                AS ShooterRoleId,
    URS.displayName                   AS ShooterRole,
    COALESCE(T.indexCount, -1)        AS ShotIndex,
    COALESCE(R.id, -1)                AS ReactId,
    COALESCE(R.reactMode, 2)          AS ReactModeId,
    COALESCE(RM.displayName, '')      AS ReactMode,
    COALESCE(R.reactType, -1)         AS ReactTypeId,
    COALESCE(RT.displayName, '')      AS ReactType,
    COALESCE(R.hitUserId, -1)         AS TargetUserId,
    COALESCE(UH.username, '')         AS TargetUserName,
    IFNULL(PH.role, 3)                AS TargetRoleId,
    URT.displayName                   AS TargetRole,
    COALESCE(R.hitTargetName, '')     AS TargetName,
    COALESCE(R.hitBoneName, '')       AS TargetBoneName,
    COALESCE(R.targetKilled, 0)       AS TargetKilled,
    COALESCE(R.objectHitLocationX, 0) AS HitLocationX,
    COALESCE(R.objectHitLocationY, 0) AS HitLocationY,
    COALESCE(R.objectHitTagLocation, '') AS HitLocationTag,
    COALESCE(R.hitPrecision, 0)       AS HitPrecision,
    COALESCE(R.distance, 0)           AS HitTargetDistance,
    COALESCE(R.reactTime, 0)          AS ReactionTime,
    COALESCE(R.timeStamp, 0)          AS TimeStamp,
    COUNT(DISTINCT R.id)              AS NbHit,
    COUNT(DISTINCT RK.srcEventIndex, RK.hitTargetName) AS NbKilled
FROM sessions S
LEFT JOIN participates      PS  ON (S.id = PS.sessionId)
LEFT JOIN participates      PH  ON (S.id = PH.sessionId)
LEFT JOIN triggerevents     T   ON (S.id = T.sessionId)
LEFT JOIN triggereventtypes TT  ON (TT.id = T.type)
LEFT JOIN sessiontypes      ST  ON (ST.id = S.sessionType)
LEFT JOIN reactevents       R   ON (T.indexCount = R.srcEventIndex AND T.sessionId = R.srcEventSessionId)
LEFT JOIN users             UH  ON (UH.id = R.hitUserId)
LEFT JOIN users             US  ON (US.id = T.srcUserId OR US.id = PS.userId)
LEFT JOIN reacteventtypes   RT  ON (RT.id = R.reactType)
LEFT JOIN reacteventmodes   RM  ON (RM.id = COALESCE(R.reactMode, 2))
LEFT JOIN reactevents       RK  ON (R.id = RK.id AND RK.targetKilled = 1)
LEFT JOIN userroles         URS ON (URS.id = IFNULL(PS.role, 3))
LEFT JOIN userroles         URT ON (URT.id = IFNULL(PH.role, 3))
GROUP BY SessionId, ShooterId, ShotIndex, TargetName
ORDER BY SessionId, ShooterId, ShotIndex, ReactId;
