# language: fr

@api @premium @multi-device @mvp
Fonctionnalité: Détection et gestion des conflits de streaming multi-device Premium

  En tant qu'abonné Premium
  Je peux écouter sur plusieurs appareils (iPhone, iPad, Android, Web)
  Mais un seul stream audio peut être actif à la fois
  Afin de respecter les conditions d'abonnement Premium individuel

  Contexte:
    Étant donné un utilisateur avec abonnement Premium actif
    Et plusieurs appareils enregistrés sur le compte :
      | device_id      | platform | nom                  | last_seen           |
      | iphone-123     | iOS      | iPhone de Jean       | 2026-02-03 14:00:00 |
      | ipad-456       | iOS      | iPad Pro             | 2026-02-03 12:30:00 |
      | android-789    | Android  | Samsung Galaxy       | 2026-02-02 18:00:00 |
      | web-abc        | Web      | Chrome MacBook       | 2026-02-03 10:00:00 |

  # ============================================================================
  # DÉTECTION STREAM ACTIF ET CONFLIT
  # ============================================================================

  Scénario: Premier stream - aucun conflit
    Étant donné aucun stream n'est actuellement actif sur le compte
    Quand l'utilisateur démarre la lecture sur "iPhone de Jean"
    Alors le stream doit démarrer normalement
    Et une session active doit être enregistrée dans Redis :
      | user_id       | user-123           |
      | device_id     | iphone-123         |
      | started_at    | 2026-02-03 14:00:00|
      | content_id    | content-xyz        |
      | stream_token  | token-abc123       |
    Et le TTL Redis doit être de 2 heures

  Scénario: Tentative de stream simultané sur second appareil
    Étant donné un stream actif sur "iPhone de Jean" depuis 10 minutes
    Quand l'utilisateur tente de démarrer la lecture sur "iPad Pro"
    Alors une réponse HTTP 409 Conflict doit être retournée
    Et le message doit indiquer :
      """
      Un contenu est déjà en cours de lecture sur "iPhone de Jean".
      Voulez-vous arrêter la lecture sur cet appareil et continuer ici ?
      """
    Et les options proposées doivent être :
      | option              | action                     |
      | Continuer ici       | kill_previous_session      |
      | Annuler             | cancel_new_session         |

  Scénario: Utilisateur choisit "Continuer ici" - kill de l'ancienne session
    Étant donné un stream actif sur "iPhone de Jean"
    Et l'utilisateur tente de lire sur "iPad Pro"
    Et le conflit est détecté
    Quand l'utilisateur choisit "Continuer ici"
    Alors l'ancienne session sur "iPhone de Jean" doit être terminée immédiatement
    Et un message WebSocket doit être envoyé à "iPhone de Jean" :
      """
      {"type": "stream_stopped", "reason": "playback_started_on_other_device", "device": "iPad Pro"}
      """
    Et la lecture sur "iPhone de Jean" doit s'arrêter avec notification :
      """
      Lecture arrêtée : un autre appareil utilise votre compte Premium.
      """
    Et le nouveau stream sur "iPad Pro" doit démarrer normalement

  Scénario: Utilisateur choisit "Annuler" - maintien de la session actuelle
    Étant donné un stream actif sur "iPhone de Jean"
    Et l'utilisateur tente de lire sur "iPad Pro"
    Et le conflit est détecté
    Quand l'utilisateur choisit "Annuler"
    Alors la session sur "iPhone de Jean" doit continuer normalement
    Et aucun stream ne doit démarrer sur "iPad Pro"
    Et l'utilisateur doit être redirigé vers l'écran d'accueil sur "iPad Pro"

  # ============================================================================
  # GESTION AUTOMATIQUE DES SESSIONS EXPIRÉES
  # ============================================================================

  Scénario: Session expirée automatiquement après pause prolongée
    Étant donné un stream actif sur "iPhone de Jean"
    Et l'utilisateur met en pause à 14:00:00
    Et le TTL Redis est configuré pour expirer après 30 minutes de pause
    Quand il est 14:35:00 (>30 min de pause)
    Alors la session Redis doit expirer automatiquement
    Et l'utilisateur peut démarrer un nouveau stream sur n'importe quel appareil
    Et aucun conflit ne doit être détecté

  Scénario: Heartbeat maintient la session active pendant la lecture
    Étant donné un stream actif sur "iPhone de Jean"
    Quand l'application envoie un heartbeat toutes les 30 secondes
    Alors le TTL Redis doit être renouvelé à 2 heures à chaque heartbeat
    Et la session doit rester active tant que les heartbeats continuent
    Et si 3 heartbeats consécutifs échouent, la session doit expirer

  Scénario: Fermeture propre de l'application libère la session
    Étant donné un stream actif sur "iPhone de Jean"
    Quand l'utilisateur ferme proprement l'application (swipe kill ou logout)
    Alors une requête "end_session" doit être envoyée à l'API
    Et la session Redis doit être immédiatement supprimée
    Et l'utilisateur peut démarrer un stream sur un autre appareil sans délai

  # ============================================================================
  # CAS LIMITES ET EDGE CASES
  # ============================================================================

  Scénario: Crash application sans fermeture propre
    Étant donné un stream actif sur "iPhone de Jean"
    Quand l'application crash sans envoyer "end_session"
    Alors la session Redis reste active avec son TTL
    Et après 2 minutes sans heartbeat, la session doit être marquée "stale"
    Et un nouveau stream peut être démarré après 2 minutes sans heartbeat
    Ou l'utilisateur peut forcer le kill via le conflit modal

  Scénario: Connexion réseau perdue pendant stream
    Étant donné un stream actif sur "iPhone de Jean"
    Quand la connexion réseau est perdue pendant 5 minutes
    Alors les heartbeats échouent mais l'app continue en buffer
    Et après 3 heartbeats manqués (90 secondes), la session est considérée "stale"
    Et un autre appareil peut démarrer un stream après 90 secondes

  Scénario: Deux appareils tentent de démarrer simultanément (race condition)
    Étant donné aucun stream actif
    Quand "iPhone de Jean" et "iPad Pro" tentent de démarrer un stream à la même milliseconde
    Alors le premier à obtenir le lock Redis doit réussir
    Et le second doit recevoir un conflit 409
    Et un mécanisme de lock distribué (Redis SET NX) doit être utilisé

  Scénario: Utilisateur bascule rapidement entre appareils (<10s)
    Étant donné un stream sur "iPhone de Jean"
    Quand l'utilisateur kill la session et démarre sur "iPad Pro"
    Et tente de redémarrer sur "iPhone de Jean" 5 secondes après
    Alors le système doit détecter le conflit avec "iPad Pro"
    Et proposer à nouveau de kill la session iPad
    Et un délai de grâce de 5 secondes doit être respecté pour éviter les boucles

  # ============================================================================
  # GESTION UTILISATEUR GRATUIT (pas de multi-device)
  # ============================================================================

  Scénario: Utilisateur gratuit tente de streamer sur 2 appareils
    Étant donné un utilisateur avec abonnement gratuit (pas Premium)
    Et un stream actif sur "iPhone de Jean"
    Quand l'utilisateur tente de lire sur "iPad Pro"
    Alors une réponse HTTP 403 Forbidden doit être retournée
    Et le message doit indiquer :
      """
      Le multi-device nécessite un abonnement Premium.
      Actuellement en lecture sur "iPhone de Jean".
      Passez à Premium pour écouter sur plusieurs appareils.
      """
    Et un bouton "Passer à Premium" doit être proposé

  # ============================================================================
  # INTERFACE ADMIN & GESTION DES CONFLITS
  # ============================================================================

  Scénario: Dashboard admin - voir sessions actives par utilisateur
    Étant donné un administrateur connecté au dashboard
    Quand l'admin recherche l'utilisateur "user-123"
    Alors les sessions actives doivent être affichées :
      | device_id   | platform | started_at          | content_id   | duration |
      | iphone-123  | iOS      | 2026-02-03 14:00:00 | content-xyz  | 15:30    |
    Et l'admin doit pouvoir "Terminer la session" manuellement

  Scénario: Support client - résolution conflit bloqué
    Étant donné un utilisateur signale ne pas pouvoir lire sur aucun appareil
    Et une session "fantôme" existe dans Redis (crash + heartbeat bloqué)
    Quand le support client force la suppression de la session Redis
    Alors la clé Redis "active_stream:user-123" doit être supprimée
    Et l'utilisateur doit pouvoir redémarrer immédiatement

  # ============================================================================
  # MÉTRIQUES & MONITORING
  # ============================================================================

  Scénario: Logging des conflits pour analytics
    Étant donné un conflit est détecté entre "iPhone de Jean" et "iPad Pro"
    Quand le conflit est résolu par kill de session
    Alors un événement analytics doit être loggé :
      | event_type                | stream_conflict_resolved  |
      | user_id                   | user-123                  |
      | previous_device           | iphone-123                |
      | new_device                | ipad-456                  |
      | resolution                | kill_previous             |
      | previous_session_duration | 900                       |
      | timestamp                 | 2026-02-03 14:15:00       |
    Et ces métriques doivent être disponibles dans le dashboard

  Scénario: Alerte monitoring - taux de conflits élevé
    Étant donné le système monitore les conflits de stream
    Quand le taux de conflits dépasse 15% des nouvelles sessions sur 1 heure
    Alors une alerte Slack doit être envoyée à l'équipe technique
    Et le message doit indiquer :
      """
      ⚠️ Taux de conflits stream élevé : 18% (seuil : 15%)
      Sessions impactées : 234 sur 1300
      Action recommandée : vérifier expiration Redis et heartbeats
      """

  # ============================================================================
  # COMPATIBILITÉ AVEC D'AUTRES FEATURES
  # ============================================================================

  Scénario: Radio live avec conflit de stream
    Étant donné un utilisateur écoute une radio live sur "iPhone de Jean"
    Quand l'utilisateur démarre un stream sur "iPad Pro" et kill la session iPhone
    Alors la radio live doit s'arrêter sur iPhone
    Et le nouveau stream sur iPad peut être une radio live ou contenu normal
    Et la progression audio-guide (si applicable) doit être sauvegardée

  Scénario: Mode offline ne déclenche PAS de conflit
    Étant donné un stream actif en ligne sur "iPhone de Jean"
    Quand l'utilisateur écoute un contenu téléchargé en mode offline sur "iPad Pro"
    Alors aucun conflit ne doit être détecté
    Car le mode offline ne consomme pas de stream en ligne
    Et les deux lectures peuvent coexister

  Scénario: Multi-device avec partage familial (post-MVP)
    Étant donné la fonctionnalité de partage familial est activée (post-MVP)
    Et le compte principal a 3 profils famille
    Quand chaque profil démarre un stream sur son appareil
    Alors jusqu'à 3 streams simultanés doivent être autorisés
    Et la détection de conflit doit s'appliquer par profil (1 stream/profil)
