# language: fr

Fonctionnalité: API - Création et gestion d'audio-guides multi-séquences
  En tant que système backend
  Je veux exposer des endpoints pour créer et gérer les audio-guides
  Afin de permettre aux créateurs de publier des expériences guidées

  Contexte:
    Étant donné que l'API RoadWave est démarrée
    Et que le créateur "guide@example.com" est authentifié avec un token JWT valide
    Et que son compte est vérifié (email_verified: true)

  # 16.1.2 - Endpoints de création

  Scénario: POST /api/v1/audio-guides - Création d'un audio-guide
    Étant donné la requête suivante:
      """json
      {
        "title": "Safari du Paugre",
        "description": "Découvrez les animaux du parc en voiture sur un circuit de 5km",
        "mode": "voiture",
        "vitesse_recommandee": "30-50 km/h",
        "tags": ["nature", "animaux", "famille"],
        "classification_age": "tout_public",
        "zone_diffusion": {
          "type": "polygon",
          "coordinates": [[2.5678, 43.1234], [2.5690, 43.1245], [2.5700, 43.1250]]
        }
      }
      """
    Quand je fais un POST sur "/api/v1/audio-guides"
    Alors le code HTTP de réponse est 201
    Et le corps de réponse contient:
      | champ              | valeur                     |
      | id                 | UUID généré                |
      | status             | draft                      |
      | creator_id         | ID du créateur             |
      | sequences_count    | 0                          |
      | created_at         | Timestamp actuel           |

  Scénario: Validation du titre (longueur 5-100 caractères)
    Étant donné la requête avec titre "ABC"
    Quand je fais un POST sur "/api/v1/audio-guides"
    Alors le code HTTP de réponse est 400
    Et le message d'erreur est "title: doit contenir entre 5 et 100 caractères"

  Scénario: Validation de la description (longueur 10-500 caractères)
    Étant donné la requête avec description de 8 caractères
    Quand je fais un POST sur "/api/v1/audio-guides"
    Alors le code HTTP de réponse est 400
    Et le message d'erreur est "description: doit contenir entre 10 et 500 caractères"

  Plan du Scénario: Validation du mode de déplacement
    Étant donné la requête avec mode "<mode>"
    Quand je fais un POST sur "/api/v1/audio-guides"
    Alors le code HTTP de réponse est <code>

    Exemples:
      | mode      | code |
      | pieton    | 201  |
      | voiture   | 201  |
      | velo      | 201  |
      | transport | 201  |
      | avion     | 400  |
      | invalid   | 400  |

  Scénario: Validation tags (1-3 tags obligatoires)
    Étant donné la requête avec 0 tags
    Quand je fais un POST sur "/api/v1/audio-guides"
    Alors le code HTTP de réponse est 400
    Et le message d'erreur est "tags: minimum 1 tag requis, maximum 3"

  Scénario: Validation classification âge
    Étant donné la requête avec classification_age "invalide"
    Quand je fais un POST sur "/api/v1/audio-guides"
    Alors le code HTTP de réponse est 400
    Et le message d'erreur contient "classification_age: valeurs autorisées [tout_public, 13+, 16+, 18+]"

  # Ajout de séquences

  Scénario: POST /api/v1/audio-guides/{id}/sequences - Ajout première séquence
    Étant donné un audio-guide draft avec ID "ag_123"
    Et la requête suivante:
      """json
      {
        "order": 1,
        "title": "Introduction - Point d'accueil",
        "audio_file": "base64_encoded_mp3_data",
        "gps_point": {
          "latitude": 43.1234,
          "longitude": 2.5678
        },
        "rayon_declenchement": 30
      }
      """
    Quand je fais un POST sur "/api/v1/audio-guides/ag_123/sequences"
    Alors le code HTTP de réponse est 201
    Et la séquence est créée avec:
      | champ               | valeur                     |
      | sequence_id         | UUID généré                |
      | order               | 1                          |
      | duration            | Calculée depuis audio      |
      | status              | uploaded                   |

  Scénario: Validation format audio (MP3, AAC, M4A uniquement)
    Étant donné un audio-guide draft
    Et un fichier audio au format WAV
    Quand je fais un POST sur "/api/v1/audio-guides/{id}/sequences"
    Alors le code HTTP de réponse est 400
    Et le message d'erreur est "audio_file: format non supporté. Formats acceptés: MP3, AAC, M4A"

  Scénario: Validation taille audio (max 200 MB)
    Étant donné un audio-guide draft
    Et un fichier audio de 250 MB
    Quand je fais un POST sur "/api/v1/audio-guides/{id}/sequences"
    Alors le code HTTP de réponse 413
    Et le message d'erreur est "audio_file: taille maximale 200 MB dépassée"

  Scénario: Validation durée audio (max 15 minutes)
    Étant donné un audio-guide draft
    Et un fichier audio de 18 minutes
    Quand je fais un POST sur "/api/v1/audio-guides/{id}/sequences"
    Alors le code HTTP de réponse est 400
    Et le message d'erreur est "audio_file: durée maximale 15 minutes dépassée"

  Scénario: Point GPS obligatoire sauf mode piéton
    Étant donné un audio-guide en mode "voiture"
    Et une séquence sans gps_point
    Quand je fais un POST sur "/api/v1/audio-guides/{id}/sequences"
    Alors le code HTTP de réponse est 400
    Et le message d'erreur est "gps_point: obligatoire pour mode voiture"

  Scénario: Point GPS optionnel en mode piéton
    Étant donné un audio-guide en mode "pieton"
    Et une séquence sans gps_point
    Quand je fais un POST sur "/api/v1/audio-guides/{id}/sequences"
    Alors le code HTTP de réponse est 201
    Et la séquence est créée sans point GPS

  Plan du Scénario: Rayon de déclenchement par défaut selon mode
    Étant donné un audio-guide en mode "<mode>"
    Et une séquence sans rayon_declenchement spécifié
    Quand je fais un POST sur "/api/v1/audio-guides/{id}/sequences"
    Alors le rayon par défaut appliqué est <rayon>

    Exemples:
      | mode      | rayon |
      | voiture   | 30    |
      | velo      | 50    |
      | transport | 100   |

  Scénario: Validation rayon configurable (10-200m)
    Étant donné un audio-guide
    Et une séquence avec rayon_declenchement 250
    Quand je fais un POST sur "/api/v1/audio-guides/{id}/sequences"
    Alors le code HTTP de réponse est 400
    Et le message d'erreur est "rayon_declenchement: doit être entre 10 et 200 mètres"

  Scénario: Nombre maximum de séquences (50)
    Étant donné un audio-guide avec 50 séquences
    Quand je tente d'ajouter une 51ème séquence
    Alors le code HTTP de réponse est 400
    Et le message d'erreur est "Maximum 50 séquences par audio-guide atteint"

  # Modification et réordonnancement

  Scénario: PATCH /api/v1/audio-guides/{id}/sequences/{seq_id} - Modification séquence
    Étant donné une séquence existante "seq_456"
    Et la requête suivante:
      """json
      {
        "title": "Introduction - Point d'accueil (édité)",
        "rayon_declenchement": 40
      }
      """
    Quand je fais un PATCH sur "/api/v1/audio-guides/ag_123/sequences/seq_456"
    Alors le code HTTP de réponse est 200
    Et les champs modifiés sont mis à jour
    Et updated_at est mis à jour

  Scénario: PUT /api/v1/audio-guides/{id}/sequences/reorder - Réordonnancement
    Étant donné un audio-guide avec 5 séquences
    Et la requête suivante:
      """json
      {
        "sequence_orders": [
          {"sequence_id": "seq_1", "order": 1},
          {"sequence_id": "seq_4", "order": 2},
          {"sequence_id": "seq_2", "order": 3},
          {"sequence_id": "seq_3", "order": 4},
          {"sequence_id": "seq_5", "order": 5}
        ]
      }
      """
    Quand je fais un PUT sur "/api/v1/audio-guides/ag_123/sequences/reorder"
    Alors le code HTTP de réponse est 200
    Et l'ordre des séquences est mis à jour en base

  Scénario: DELETE /api/v1/audio-guides/{id}/sequences/{seq_id} - Suppression séquence
    Étant donné un audio-guide avec 3 séquences
    Quand je fais un DELETE sur "/api/v1/audio-guides/ag_123/sequences/seq_2"
    Alors le code HTTP de réponse est 204
    Et la séquence est supprimée
    Et l'ordre des séquences restantes est réajusté (1, 2)

  # Publication et validation

  Scénario: POST /api/v1/audio-guides/{id}/publish - Publication (nouveau créateur)
    Étant donné un audio-guide draft avec 3 séquences complètes
    Et que c'est le 2ème audio-guide du créateur
    Quand je fais un POST sur "/api/v1/audio-guides/ag_123/publish"
    Alors le code HTTP de réponse est 200
    Et le status passe à "pending_moderation"
    Et moderation_required est true
    Et le corps de réponse contient:
      """json
      {
        "status": "pending_moderation",
        "message": "Votre audio-guide est en cours de validation. Notre équipe le vérifiera sous 24-48h.",
        "estimated_validation": "2026-01-24T14:00:00Z"
      }
      """

  Scénario: Publication directe pour créateur expérimenté (>5 audio-guides validés)
    Étant donné un audio-guide draft avec 5 séquences
    Et que le créateur a publié 8 audio-guides validés
    Et qu'il n'a aucun strike actif
    Quand je fais un POST sur "/api/v1/audio-guides/ag_456/publish"
    Alors le code HTTP de réponse est 200
    Et le status passe à "published"
    Et moderation_required est false
    Et l'audio-guide est immédiatement visible

  Scénario: Validation nombre minimum de séquences (2)
    Étant donné un audio-guide draft avec 1 seule séquence
    Quand je fais un POST sur "/api/v1/audio-guides/ag_123/publish"
    Alors le code HTTP de réponse est 400
    Et le message d'erreur est "Minimum 2 séquences requis pour publication"

  Scénario: Alerte cohérence - Points GPS trop éloignés
    Étant donné un audio-guide en mode "pieton"
    Et une séquence au Louvre (Paris)
    Et une séquence à Lyon (465 km de distance)
    Quand je fais un POST sur "/api/v1/audio-guides/ag_123/publish"
    Alors le code HTTP de réponse est 200
    Et un warning est retourné:
      """json
      {
        "status": "pending_moderation",
        "warnings": [
          {
            "type": "distance_incohérence",
            "message": "Distance importante entre points (465 km). Vérifiez que le mode 'pieton' est approprié.",
            "severity": "warning"
          }
        ]
      }
      """

  # Gestion des brouillons

  Scénario: Sauvegarde automatique brouillon
    Étant donné un audio-guide draft non sauvegardé depuis 5 minutes
    Quand une modification est apportée via PATCH
    Alors le champ updated_at est mis à jour automatiquement
    Et le brouillon est sauvegardé en base

  Scénario: GET /api/v1/audio-guides/drafts - Liste des brouillons
    Étant donné que le créateur a 2 brouillons:
      | id     | title            | sequences_count | updated_at          |
      | ag_111 | Safari du Paugre | 3               | 2026-01-20 10:00:00 |
      | ag_222 | Visite du Louvre | 1               | 2026-01-15 14:30:00 |
    Quand je fais un GET sur "/api/v1/audio-guides/drafts"
    Alors le code HTTP de réponse est 200
    Et le corps de réponse contient les 2 brouillons
    Et ils sont triés par updated_at décroissant

  Scénario: DELETE /api/v1/audio-guides/{id} - Suppression brouillon
    Étant donné un audio-guide draft "ag_123"
    Quand je fais un DELETE sur "/api/v1/audio-guides/ag_123"
    Alors le code HTTP de réponse est 204
    Et l'audio-guide et toutes ses séquences sont supprimés
    Et les fichiers audio associés sont marqués pour suppression S3

  # Modification audio-guide publié

  Scénario: PATCH /api/v1/audio-guides/{id} - Modification métadonnées (publié)
    Étant donné un audio-guide publié "ag_789"
    Et la requête suivante:
      """json
      {
        "title": "Safari du Paugre - Version 2",
        "description": "Nouvelle description améliorée",
        "tags": ["nature", "animaux", "enfants"]
      }
      """
    Quand je fais un PATCH sur "/api/v1/audio-guides/ag_789"
    Alors le code HTTP de réponse est 200
    Et les métadonnées sont mises à jour
    Et le status reste "published" (pas de revalidation)

  Scénario: Interdiction modification mode après publication
    Étant donné un audio-guide publié en mode "voiture"
    Et la requête avec mode "pieton"
    Quand je fais un PATCH sur "/api/v1/audio-guides/{id}"
    Alors le code HTTP de réponse est 400
    Et le message d'erreur est "mode: impossible de modifier le mode après publication"

  Scénario: Interdiction modification GPS après publication
    Étant donné un audio-guide publié avec points GPS
    Et une tentative de modification des coordonnées GPS
    Quand je fais un PATCH sur "/api/v1/audio-guides/{id}/sequences/{seq_id}"
    Alors le code HTTP de réponse est 400
    Et le message d'erreur est "gps_point: impossible de modifier après publication. Créez une nouvelle version."

  # Duplication

  Scénario: POST /api/v1/audio-guides/{id}/duplicate - Duplication audio-guide
    Étant donné un audio-guide publié "ag_999" avec 12 séquences
    Quand je fais un POST sur "/api/v1/audio-guides/ag_999/duplicate"
    Alors le code HTTP de réponse est 201
    Et un nouvel audio-guide draft est créé
    Et le titre est "Safari du Paugre (copie)"
    Et toutes les séquences sont copiées avec les mêmes métadonnées
    Et les fichiers audio sont référencés (pas de duplication S3)

  # Statistiques

  Scénario: GET /api/v1/audio-guides/{id}/stats - Statistiques parcours
    Étant donné un audio-guide avec les séquences suivantes:
      | sequence | duration | gps_point          | distance_to_next |
      | 1        | 2:15     | (43.1234, 2.5678) | 150m             |
      | 2        | 3:42     | (43.1245, 2.5690) | 200m             |
      | 3        | 4:10     | (43.1250, 2.5700) | null             |
    Quand je fais un GET sur "/api/v1/audio-guides/ag_123/stats"
    Alors le code HTTP de réponse est 200
    Et le corps de réponse contient:
      """json
      {
        "sequences_count": 3,
        "total_duration": "10:07",
        "total_distance": "350m",
        "avg_sequence_duration": "3:22"
      }
      """

  # Gestion zone diffusion

  Scénario: Validation zone diffusion (polygon géographique)
    Étant donné une zone diffusion de type "polygon"
    Et les coordonnées forment un polygon valide (min 3 points)
    Quand je fais un POST sur "/api/v1/audio-guides"
    Alors la zone est validée avec PostGIS ST_IsValid
    Et stockée en type geography

  Scénario: Zone diffusion via API Nominatim (ville)
    Étant donné une zone diffusion de type "city"
    Et la valeur "Paris"
    Quand je fais un POST sur "/api/v1/audio-guides"
    Alors l'API interroge Nominatim pour récupérer le polygon de Paris
    Et le polygon est stocké en base

  # Cas d'erreur

  Scénario: Authentification requise
    Étant donné une requête sans token JWT
    Quand je fais un POST sur "/api/v1/audio-guides"
    Alors le code HTTP de réponse est 401
    Et le message d'erreur est "Authentification requise"

  Scénario: Compte non vérifié
    Étant donné un créateur avec email_verified: false
    Quand je fais un POST sur "/api/v1/audio-guides"
    Alors le code HTTP de réponse est 403
    Et le message d'erreur est "Vérification email requise pour créer des audio-guides"

  Scénario: Modification audio-guide d'un autre créateur (interdite)
    Étant donné un audio-guide appartenant au créateur "creator_A"
    Et une requête authentifiée par "creator_B"
    Quand je fais un PATCH sur "/api/v1/audio-guides/{id}"
    Alors le code HTTP de réponse est 403
    Et le message d'erreur est "Vous n'êtes pas autorisé à modifier cet audio-guide"

  Scénario: Audio-guide inexistant
    Quand je fais un GET sur "/api/v1/audio-guides/ag_nonexistant"
    Alors le code HTTP de réponse est 404
    Et le message d'erreur est "Audio-guide non trouvé"

  Scénario: Séquence inexistante
    Étant donné un audio-guide "ag_123"
    Quand je fais un DELETE sur "/api/v1/audio-guides/ag_123/sequences/seq_nonexistant"
    Alors le code HTTP de réponse est 404
    Et le message d'erreur est "Séquence non trouvée"

  Scénario: Suppression audio-guide avec utilisateurs actifs
    Étant donné un audio-guide publié "ag_456"
    Et 20 utilisateurs ont une progression active
    Quand je fais un DELETE sur "/api/v1/audio-guides/ag_456"
    Alors le code HTTP de réponse est 200
    Et l'audio-guide est marqué "deleted" (soft delete)
    Et les progressions utilisateurs sont archivées pendant 30 jours
    Et un warning est retourné: "20 utilisateurs actifs. Progressions archivées 30 jours."
