# Gestion des Secteurs et de la Carte

Ce document centralise toutes les règles de gestion des secteurs et de la carte dans l'application Geosector.

**Dernière mise à jour** : Décembre 2024 - Améliorations de la détection d'adjacence et de l'ergonomie du drag

## Table des matières

1. [Vue d'ensemble](#vue-densemble)
2. [Structure des données](#structure-des-données)
3. [Modes de la carte](#modes-de-la-carte)
4. [Création d'un secteur](#création-dun-secteur)
5. [Gestion des secteurs adjacents](#gestion-des-secteurs-adjacents)
6. [Modification d'un secteur](#modification-dun-secteur)
7. [Suppression d'un secteur](#suppression-dun-secteur)
8. [Affichage des secteurs](#affichage-des-secteurs)
9. [Affichage des passages](#affichage-des-passages)
10. [Permissions et rôles](#permissions-et-rôles)
11. [Synchronisation API/Hive](#synchronisation-apihive)
12. [Interactions utilisateur](#interactions-utilisateur)
13. [Bonnes pratiques](#bonnes-pratiques)

## Vue d'ensemble

La carte administrative (`AdminMapPage`) permet aux administrateurs de gérer les secteurs géographiques d'une opération. Chaque secteur est un polygone défini par des coordonnées GPS et peut contenir des passages (adresses à visiter).

### Technologies utilisées
- **flutter_map** avec **MapBox** pour l'affichage de la carte
- **Hive** pour le stockage local des données
- **ValueListenableBuilder** pour la mise à jour réactive de l'interface

## Structure des données

### SectorModel
```dart
{
  id: int,                  // Identifiant unique
  libelle: String,          // Nom du secteur
  color: String,            // Couleur hexadécimale (#RRGGBB)
  sector: String            // Coordonnées "lat/lng#lat/lng#..."
}
```

### PassageModel
```dart
{
  id: int,
  fk_sector: int,          // ID du secteur
  fk_user: int,            // ID de l'utilisateur assigné
  fk_type: int,            // Type de passage (1-6)
  gps_lat: String,         // Latitude
  gps_lng: String,         // Longitude
  numero: String,          // Numéro de rue
  rue: String,             // Nom de la rue
  ville: String,           // Ville
  // ... autres champs
}
```

### Types de passages
- **1** : Effectué (vert)
- **2** : À finaliser (orange)
- **3** : Refusé (rouge)
- **4** : Don (bleu)
- **5** : Lot (violet)
- **6** : Maison vide (gris)

## Modes de la carte

La carte peut être dans l'un des modes suivants :

### MapMode.view (Mode visualisation)
- Mode par défaut
- Permet de naviguer sur la carte
- Affiche les secteurs et passages
- Permet la sélection d'un secteur via la combobox

### MapMode.drawing (Mode création)
- Activé par le bouton "Créer un secteur"
- Affiche une carte d'aide explicative
- Permet de dessiner un nouveau secteur en cliquant sur la carte
- Points verts pour le premier point, bleus pour les suivants
- Fermeture du polygone en cliquant sur le premier point

### MapMode.editing (Mode édition)
- Activé par le bouton "Modifier un secteur"
- Permet de modifier les contours d'un secteur existant
- Sélectionner un secteur par clic ou via la combobox puis cliquer "Modifier"
- Points orange draggables avec magnétisme automatique
- Ajout de points via les points intermédiaires gris
- Suppression de points avec clic droit ou Ctrl+clic

### MapMode.deleting (Mode suppression)
- Activé par le bouton "Supprimer un secteur"
- Affiche une carte d'aide avec avertissements
- Permet de sélectionner un secteur à supprimer en cliquant dessus
- Le secteur sélectionné apparaît en rouge

## Création d'un secteur

### Processus de création

1. **Dessin du secteur**
   - L'administrateur clique sur le bouton "Créer un secteur"
   - Il dessine le contour en cliquant sur la carte (minimum 3 points)
   - Il ferme le polygone en cliquant sur le premier point

2. **Dialog de création**
   - Nom du secteur (obligatoire)
   - Couleur du secteur (sélection dans une palette)
   - Sélection des membres assignés (au moins un obligatoire)

3. **Envoi à l'API**
   ```json
   {
     "id": 0,
     "libelle": "Nom du secteur",
     "color": "#2196F3",
     "sector": "lat/lng#lat/lng#...",
     "operation_id": 3124,
     "fk_entite": 5,
     "users": [9999980, 9999985]
   }
   ```

4. **Réponse de l'API**
   ```json
   {
     "status": "success",
     "sector": { /* ou sector_id */ },
     "passages_sector": [...],
     "passages_created": 86,
     "passages_integrated": 0,
     "users_sectors": [...],
     "warning": "Avertissement si débordement départemental",
     "intersecting_departments": [
       {
         "code_dept": "35",
         "nom_dept": "Ille-et-Vilaine",
         "percentage_overlap": 85.2
       }
     ]
   }
   ```

5. **Traitement de la réponse**
   - Le secteur est sauvegardé dans Hive
   - Les passages sont créés avec les coordonnées GPS
   - Les associations utilisateur-secteur sont traitées
   - La carte se centre sur le nouveau secteur

### Règles de création
- Un secteur doit avoir au moins 3 points
- Le nom est obligatoire
- Au moins un membre doit être assigné
- Les coordonnées sont au format "latitude/longitude"
- Le dernier point doit fermer le polygone
- Les secteurs adjacents sont automatiquement corrigés (voir section dédiée)

## Gestion des secteurs adjacents

### Vue d'ensemble

L'application gère automatiquement la création de secteurs adjacents (partageant une bordure commune) sans générer d'erreur de chevauchement. Cette fonctionnalité est cruciale pour permettre un découpage précis du territoire.

### Correction automatique des points

#### Méthode `_correctPointsForAdjacency`

Cette méthode est appelée automatiquement lors de :
- La validation d'un nouveau secteur (création)
- La validation d'un secteur modifié (modification)

**Paramètres de correction :**
- **Distance de détection** : 10 mètres
- **Décalage de correction** : 2 mètres vers l'intérieur
- **Décalage fort** : 5 mètres (si chevauchement persistant)

**Processus en deux passes :**

1. **Première passe - Détection et correction des segments adjacents**
   ```dart
   // Pour chaque segment du nouveau secteur
   // Vérifier s'il est proche d'un segment existant
   // Si oui, corriger les deux points du segment
   ```

2. **Deuxième passe - Vérification et correction forte**
   ```dart
   // Appel à _ensureNoIntersection
   // Si chevauchement détecté → _applyStrongerCorrection
   ```

### Calcul du décalage vers l'intérieur

#### Méthode `_offsetPointInward`

**Principe :**
- Calcule la bissectrice des segments adjacents
- Utilise le produit vectoriel pour déterminer la direction intérieure
- Applique un décalage en tenant compte de la latitude

**Formule de conversion :**
```dart
offsetDegreesLat = offsetMeters / 111320.0
offsetDegreesLng = offsetMeters / (111320.0 * cos(latitude))
```

### Détection intelligente des chevauchements

#### Méthode `_doPolygonsOverlap`

**Tolérance d'adjacence** : 2 mètres

**Règles de détection améliorées :**
1. **Points intérieurs** : Un point est considéré à l'intérieur seulement s'il est à plus de 2m du bord
2. **Vertices partagés** : Les vertices à moins de 5m de distance sont considérés comme partagés et ignorés
3. **Segments adjacents** : Deux segments alignés et proches ne sont pas considérés comme un chevauchement
4. **Seuil de détection** : Il faut au moins 3 points intérieurs ou 3 intersections pour détecter un chevauchement réel
5. **Exclusion du secteur en cours** : Lors de la modification, le secteur lui-même est exclu de la détection

#### Méthode `_areSegmentsAdjacent`

Détermine si deux segments sont adjacents (partagent une partie commune) :
- Vérifie l'alignement des segments
- Vérifie la proximité des points aux lignes opposées
- Retourne `true` si les segments sont sur la même ligne

### Magnétisme automatique

Lors de la sélection d'un secteur pour modification :
- Application automatique du magnétisme aux points proches
- Visualisation immédiate des ajustements
- Message d'information si des points ont été magnétisés

### Exemple de création de secteurs adjacents

```
Secteur A (existant) :     Nouveau secteur B :
+--------+                 +--------+
|        |                 |        |
|   A    | <-- bordure --> |   B    |
|        |     commune     |        |
+--------+                 +--------+
```

**Résultat après correction automatique :**
- Les points de B sur la bordure commune sont décalés de 2m vers l'intérieur
- Aucune erreur de chevauchement
- Les secteurs restent visuellement adjacents

### Messages utilisateur

- **Correction appliquée** : "Les points ont été ajustés automatiquement pour éviter les chevauchements" (bleu)
- **Chevauchement détecté** : "Le nouveau secteur chevauche avec le secteur [nom]" (rouge)
- **Logging détaillé** : En cas de chevauchement détecté, les coordonnées des zones problématiques sont loggées

## Modification d'un secteur

### Processus de modification

1. **Sélection du secteur**
   - Via la combobox ou clic sur la carte
   - Bouton "Modifier" dans la barre d'outils

2. **Mode édition**
   - Application automatique du magnétisme dès la sélection
   - Points draggables instantanément (clic et drag immédiat)
   - Points orange avec zone de détection élargie (50x50px)
   - Ajout de points via les points intermédiaires gris
   - Suppression avec clic droit ou Ctrl+clic
   - Désactivation du drag de la carte pendant le déplacement d'un point

3. **Validation**
   - Mêmes vérifications que pour la création
   - Application de `_correctPointsForAdjacency` avec exclusion du secteur en cours
   - Dialog pour modifier nom, couleur et membres
   - Les membres déjà affectés sont automatiquement présélectionnés
   - Affichage d'un dialog récapitulatif avec statistiques

### Règles de modification
- Minimum 3 points maintenu
- Correction automatique des adjacences
- Même processus de validation que la création
- Les passages sont automatiquement réaffectés selon le nouveau contour

## Suppression d'un secteur

### Processus de suppression

1. **Sélection du secteur**
   - L'administrateur clique sur "Supprimer un secteur"
   - Il clique sur le secteur à supprimer (surbrillance rouge)

2. **Dialog de confirmation**
   - Affichage du nom du secteur
   - Avertissements sur les conséquences

3. **Règles de suppression des passages**
   - Passages "à finaliser" (type 2) sans nom d'habitant → **supprimés**
   - Autres passages → **conservés mais réassignés au secteur 0**

4. **Réponse de l'API**
   ```json
   {
     "status": "success",
     "passages_deleted": 45,
     "passages_reassigned": 125
   }
   ```

5. **Mise à jour locale**
   - Suppression du secteur de Hive
   - Mise à jour des passages selon les règles
   - Actualisation automatique de la carte

## Affichage des secteurs

### Représentation visuelle
- **Polygones colorés** avec transparence (30% en normal, 50% si sélectionné)
- **Bordure** de la couleur du secteur (épaisseur 2px, 3px si sélectionné)
- **Mode suppression** : secteur en rouge avec bordure épaisse (4px)

### Filtrage par secteur
- Combobox en haut à gauche
- "Tous les secteurs" par défaut
- Sélection d'un secteur → zoom et centrage automatique
- Filtrage des passages affichés

## Affichage des passages

### Représentation visuelle
- **Marqueurs circulaires** de 14x14 pixels
- **Couleur principale** selon le type de passage
- **Bordure blanche** de 1px
- **Cliquables** pour afficher les détails

### Conditions d'affichage
- Coordonnées GPS valides (gps_lat et gps_lng)
- Type de passage reconnu (1-6)
- Appartenance au secteur sélectionné (si filtre actif)

### Informations au clic
- Adresse complète
- Nom de l'habitant (si disponible)
- Type de passage
- Informations de règlement (si applicable)
- Boutons d'édition/suppression

## Permissions et rôles

### Accès à la carte administrative
- **Rôle minimum requis** : Admin Amicale (rôle > 1)
- **Rôle 1 (Membre)** : Pas d'accès à la carte admin
- **Rôle 2+ (Admin)** : Accès complet aux fonctionnalités

### Actions autorisées
- **Création de secteur** : Admin+
- **Modification de secteur** : Admin+
- **Suppression de secteur** : Admin+
- **Visualisation** : Admin+

## Synchronisation API/Hive

### Principe "API First"
1. Toute modification passe d'abord par l'API
2. En cas de succès, mise à jour de Hive
3. En cas d'échec, aucune modification locale

### Flux de données

#### Chargement initial
```
API (login) → Secteurs/Passages → Hive → ValueListenableBuilder → UI
```

#### Création de secteur
```
UI → API → Réponse (secteur + passages) → Hive → Auto-refresh UI
```

#### Suppression de secteur
```
UI → API → Réponse (stats) → Mise à jour Hive → Auto-refresh UI
```

### Gestion des erreurs
- Affichage de SnackBar avec message d'erreur
- Pas de modification locale en cas d'échec API
- Log des erreurs pour debug

### Performance
- Utilisation de box caching dans les repositories
- ValueListenableBuilder pour éviter les rebuilds inutiles
- Chargement asynchrone des données

## Interactions utilisateur

### Gestion du drag des points

**Technologie utilisée** : `Listener` avec `onPointerDown`/`onPointerMove`/`onPointerUp`

**Avantages :**
- Démarrage instantané du drag au clic (onPointerDown)
- Pas de conflit avec les gestes de la carte
- Conversion directe des coordonnées écran en coordonnées géographiques

**Interactions supportées :**
- **Clic gauche** : Démarre le drag immédiatement
- **Clic droit / Ctrl+clic** : Supprime le point
- **Clic sur premier point (mode dessin)** : Ferme le polygone si 3+ points
- **Drag** : Déplace le point avec magnétisme en temps réel

### Dialog récapitulatif

Après chaque opération (création/modification/suppression), un dialog affiche :
- **Statistiques des passages** : créés, mis à jour, orphelins, total
- **Avertissements départementaux** : si le secteur est à cheval sur plusieurs départements
- **Icônes et couleurs** adaptées selon le type d'opération

## Bonnes pratiques

### Pour les développeurs

1. **Toujours passer par l'API** pour les modifications
2. **Utiliser les repositories** pour l'accès aux données
3. **Ne pas faire de setState** dans les ValueListenableBuilder
4. **Gérer les erreurs** avec ApiException
5. **Valider les données** avant envoi à l'API
6. **Logger les actions importantes** pour le debug
7. **Utiliser les mêmes méthodes de validation** pour création et modification :
   - `_correctPointsForAdjacency` pour la correction automatique
   - `_doPolygonsOverlap` pour la détection de chevauchement
   - `_isValidPolygon` pour la validation de base
8. **Sauvegarder le contexte parent** avant d'ouvrir des dialogs pour éviter les erreurs de contexte
9. **Implémenter le chargement des associations** (ex: UserSectorModel) pour présélectionner les données

### Pour les utilisateurs

1. **Dessiner des secteurs cohérents** (pas de croisements)
2. **Nommer clairement** les secteurs
3. **Assigner les bons membres** dès la création
4. **Vérifier avant suppression** (action irréversible)
5. **Utiliser des couleurs distinctes** pour différencier les secteurs
6. **Pour les secteurs adjacents** :
   - Dessiner normalement sans se soucier de la précision
   - Le système ajuste automatiquement les bordures
   - Vérifier le résultat après la correction automatique
7. **Pour la modification des secteurs** :
   - Cliquer directement sur un point pour le déplacer (pas besoin de maintenir)
   - Utiliser les points gris intermédiaires pour ajouter des sommets
   - Clic droit ou Ctrl+clic pour supprimer un point
   - Le magnétisme s'applique automatiquement aux bordures adjacentes