import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:geosector_app/core/data/models/sector_model.dart';
import 'package:geosector_app/core/data/models/passage_model.dart';
import 'package:geosector_app/core/services/api_service.dart';
import 'package:geosector_app/core/constants/app_keys.dart';
import 'package:geosector_app/core/repositories/passage_repository.dart';
import 'package:geosector_app/core/services/data_loading_service.dart';

class SectorRepository extends ChangeNotifier {
  // Constructeur sans paramètres - utilise ApiService.instance
  SectorRepository();
  // Cache de la box pour éviter les vérifications répétées
  Box<SectorModel>? _cachedSectorBox;
  
  // Utiliser un getter lazy pour n'accéder à la boîte que lorsque nécessaire
  Box<SectorModel> get _sectorBox {
    if (_cachedSectorBox == null) {
      if (!Hive.isBoxOpen(AppKeys.sectorsBoxName)) {
        throw Exception('La boîte ${AppKeys.sectorsBoxName} n\'est pas ouverte. Initialisez d\'abord l\'application.');
      }
      _cachedSectorBox = Hive.box<SectorModel>(AppKeys.sectorsBoxName);
      debugPrint('SectorRepository: Box ${AppKeys.sectorsBoxName} mise en cache');
    }
    return _cachedSectorBox!;
  }

  // Constante pour l'ID par défaut
  static const int defaultSectorId = 1;

  // Méthode publique pour réinitialiser le cache (ex: après nettoyage complet)
  void resetCache() {
    _cachedSectorBox = null;
    debugPrint('🔄 Cache SectorRepository réinitialisé');
  }

  // Récupérer tous les secteurs
  List<SectorModel> getAllSectors() {
    return _sectorBox.values.toList();
  }

  // Récupérer un secteur par son ID
  SectorModel? getSectorById(int id) {
    return _sectorBox.get(id);
  }

  // Sauvegarder un secteur
  Future<void> saveSector(SectorModel sector) async {
    await _sectorBox.put(sector.id, sector);
    resetCache(); // Réinitialiser le cache après modification
    notifyListeners();
  }

  // Supprimer un secteur
  Future<void> deleteSector(int id) async {
    await _sectorBox.delete(id);
    resetCache(); // Réinitialiser le cache après modification
    notifyListeners();
  }

  // Sauvegarder les secteurs dans la base de données locale
  Future<void> saveSectors(List<SectorModel> sectors) async {
    // Vider la box avant d'ajouter les nouveaux secteurs
    await _sectorBox.clear();

    // Ajouter les nouveaux secteurs
    for (final sector in sectors) {
      await _sectorBox.put(sector.id, sector);
    }
    resetCache(); // Réinitialiser le cache après modification massive
    notifyListeners();
  }

  // Traitement des données de secteurs depuis l'API
  Future<void> processSectorsData(dynamic sectorsData) async {
    try {
      debugPrint('Traitement des données des secteurs...');

      // Vérifier que les données sont au bon format
      if (sectorsData == null) {
        debugPrint('Aucune donnée de secteur à traiter');
        return;
      }

      List<dynamic> sectorsList;
      if (sectorsData is List) {
        sectorsList = sectorsData;
      } else if (sectorsData is Map && sectorsData.containsKey('data')) {
        sectorsList = sectorsData['data'] as List<dynamic>;
      } else {
        debugPrint('Format de données de secteurs non reconnu');
        return;
      }

      // Vider la boîte avant d'ajouter les nouvelles données
      await _sectorBox.clear();

      // Traiter chaque secteur
      int count = 0;
      for (final sectorData in sectorsList) {
        try {
          final sector = SectorModel.fromJson(sectorData);
          await _sectorBox.put(sector.id, sector);
          count++;
        } catch (e) {
          debugPrint('Erreur lors du traitement d\'un secteur: $e');
        }
      }

      debugPrint('$count secteurs traités et stockés');
      resetCache(); // Réinitialiser le cache après traitement des données API
      notifyListeners();
    } catch (e) {
      debugPrint('Erreur lors du traitement des secteurs: $e');
    }
  }

  // Récupérer les secteurs depuis l'API
  Future<List<SectorModel>> fetchSectorsFromApi() async {
    try {
      final response = await ApiService.instance.get(AppKeys.sectorsEndpoint);
      final Map<String, dynamic> responseData = response as Map<String, dynamic>;

      if (responseData['status'] == 'success' && responseData['sectors'] != null) {
        final List<dynamic> sectorsJson = responseData['sectors'];
        final List<SectorModel> sectors = sectorsJson.map((json) => SectorModel.fromJson(json)).toList();

        // Sauvegarder les secteurs localement
        await saveSectors(sectors);
        return sectors;
      }

      return [];
    } catch (e) {
      // En cas d'erreur, retourner les secteurs locaux
      return getAllSectors();
    }
  }

  // Créer un nouveau secteur via l'API
  Future<Map<String, dynamic>> createSector(SectorModel sector, {required List<int> users, required int fkEntite, required int operationId, BuildContext? context}) async {
    try {
      // Préparer les données à envoyer
      final Map<String, dynamic> requestData = {
        ...sector.toJson(),
        'users': users,
        'fk_entite': fkEntite,
        'operation_id': operationId,
      };
      
      final response = await ApiService.instance.post(
        AppKeys.sectorsEndpoint,
        data: requestData,
      );
      
      // Vérifier si la requête a été mise en queue (mode offline)
      if (response.data != null && response.data['queued'] == true) {
        // Mode offline : NE PAS créer le secteur dans Hive
        debugPrint('⏳ Création du secteur mise en attente (mode hors ligne)');
        
        // Informer l'utilisateur si un contexte est fourni
        if (context != null && context.mounted) {
          showDialog(
            context: context,
            builder: (context) => AlertDialog(
              title: const Row(
                children: [
                  Icon(Icons.cloud_off, color: Colors.orange),
                  SizedBox(width: 8),
                  Text('Création en attente'),
                ],
              ),
              content: const Text(
                'Le secteur sera créé dès que la connexion sera rétablie.\n\n'
                'La création a été ajoutée à la file d\'attente.',
              ),
              actions: [
                TextButton(
                  onPressed: () => Navigator.of(context).pop(),
                  child: const Text('Compris'),
                ),
              ],
            ),
          );
        }
        return {
          'status': 'queued',
          'message': 'Création mise en attente'
        };
      }
      
      // Gérer la réponse correctement
      final dynamic responseRaw = response.data;
      final Map<String, dynamic> responseData = Map<String, dynamic>.from(responseRaw as Map);

      if (responseData['status'] == 'success') {
        // L'API peut retourner soit 'sector' (objet complet) soit 'sector_id' (ID seulement)
        SectorModel newSector;
        
        if (responseData['sector'] != null) {
          // Cas où l'API retourne l'objet secteur complet
          newSector = SectorModel.fromJson(responseData['sector']);
        } else if (responseData['sector_id'] != null) {
          // Cas où l'API retourne seulement l'ID du secteur créé
          final sectorId = responseData['sector_id'] is String 
              ? int.parse(responseData['sector_id']) 
              : responseData['sector_id'] as int;
          
          // Créer le secteur avec les données envoyées et l'ID reçu
          newSector = sector.copyWith(id: sectorId);
        } else {
          debugPrint('Erreur: Aucune donnée de secteur dans la réponse');
          return {
            'status': 'error',
            'message': 'Aucune donnée de secteur dans la réponse'
          };
        }
        
        // Sauvegarder le secteur
        await saveSector(newSector);
        
        // Traiter les passages retournés s'ils existent
        if (responseData['passages_sector'] != null) {
          try {
            final passagesData = responseData['passages_sector'] as List<dynamic>;
            debugPrint('Traitement de ${passagesData.length} passages retournés');
            
            // Utiliser PassageRepository pour traiter les passages
            final passageRepository = PassageRepository();
            
            // Convertir chaque passage au format complet attendu
            final List<PassageModel> passagesToSave = [];
            for (final passageData in passagesData) {
              try {
                // Caster passageData en Map<String, dynamic>
                final Map<String, dynamic> passageDataMap = Map<String, dynamic>.from(passageData as Map);
                
                // L'API retourne déjà des passages complets, on les utilise directement
                final passage = PassageModel.fromJson(passageDataMap);
                passagesToSave.add(passage);
              } catch (e) {
                debugPrint('Erreur lors du traitement d\'un passage: $e');
              }
            }
            
            // Sauvegarder tous les passages
            if (passagesToSave.isNotEmpty) {
              await passageRepository.savePassages(passagesToSave);
              debugPrint('${passagesToSave.length} passages sauvegardés');
            }
          } catch (e) {
            debugPrint('Erreur lors du traitement des passages: $e');
            // Ne pas faire échouer la création du secteur si le traitement des passages échoue
          }
        }
        
        // Traiter les users_sectors retournés s'ils existent
        if (responseData['users_sectors'] != null) {
          try {
            final usersSectorsData = responseData['users_sectors'] as List<dynamic>;
            debugPrint('Traitement de ${usersSectorsData.length} associations utilisateur-secteur');
            
            // Sauvegarder les associations dans la box UserSector via DataLoadingService
            await DataLoadingService.instance.processUserSectorsFromApi(usersSectorsData);
            
            for (final userData in usersSectorsData) {
              debugPrint('Utilisateur ${userData['first_name']} ${userData['name']} (ID: ${userData['id']}) assigné au secteur ${userData['fk_sector']}');
            }
          } catch (e) {
            debugPrint('Erreur lors du traitement des users_sectors: $e');
          }
        }
        
        // Afficher les statistiques si disponibles
        if (responseData['passages_created'] != null || responseData['passages_integrated'] != null) {
          final created = responseData['passages_created'] ?? 0;
          final integrated = responseData['passages_integrated'] ?? 0;
          debugPrint('Statistiques: $created passages créés, $integrated passages intégrés');
        }
        
        // Retourner le secteur et toutes les informations
        return {
          'status': 'success',
          'sector': newSector,
          'passages_created': responseData['passages_created'] ?? 0,
          'passages_integrated': responseData['passages_integrated'] ?? 0,
          'passages_total': (responseData['passages_created'] ?? 0) + (responseData['passages_integrated'] ?? 0),
          'warning': responseData['warning'],
          'intersecting_departments': responseData['intersecting_departments'],
        };
      }

      return {
        'status': 'error',
        'message': responseData['message'] ?? 'Erreur lors de la création'
      };
    } catch (e) {
      debugPrint('Erreur lors de la création du secteur: $e');
      rethrow;
    }
  }

  // Mettre à jour un secteur via l'API
  Future<Map<String, dynamic>> updateSector(SectorModel sector, {List<int>? users, int? chkAdressesChange}) async {
    try {
      // Préparer les données à envoyer
      final Map<String, dynamic> requestData = {
        ...sector.toJson(),
      };

      // Ajouter les utilisateurs si fournis
      if (users != null) {
        requestData['users'] = users;
      }

      // Ajouter le paramètre chk_adresses_change (par défaut 1 si non spécifié)
      requestData['chk_adresses_change'] = chkAdressesChange ?? 1;
      
      final response = await ApiService.instance.put(
        '${AppKeys.sectorsEndpoint}/${sector.id}',
        data: requestData,
      );
      
      // Vérifier si la requête a été mise en queue (mode offline)
      if (response.data != null && response.data['queued'] == true) {
        // Mode offline : Sauvegarder localement avec indicateur
        await saveSector(sector);
        debugPrint('⏳ Modification du secteur ${sector.id} mise en attente (mode hors ligne)');
        return {
          'status': 'queued',
          'message': 'Modification mise en attente'
        };
      }
      
      // Gérer la réponse correctement
      final dynamic responseRaw = response.data;
      final Map<String, dynamic> responseData = Map<String, dynamic>.from(responseRaw as Map);

      if (responseData['status'] == 'success') {
        // Sauvegarder le secteur mis à jour
        if (responseData['sector'] != null) {
          final SectorModel updatedSector = SectorModel.fromJson(responseData['sector']);
          await saveSector(updatedSector);
        }

        // Traiter les passages retournés UNIQUEMENT si chk_adresses_change = 1
        if ((chkAdressesChange ?? 1) == 1 && responseData['passages_sector'] != null) {
          try {
            final passagesData = responseData['passages_sector'] as List<dynamic>;
            debugPrint('Traitement de ${passagesData.length} passages après UPDATE (chk_adresses_change=1)');

            // Utiliser PassageRepository pour traiter les passages
            final passageRepository = PassageRepository();

            // Vider d'abord tous les passages du secteur
            await _deleteAllPassagesOfSector(sector.id);

            // Puis sauvegarder tous les passages retournés
            final List<PassageModel> passagesToSave = [];
            for (final passageData in passagesData) {
              try {
                final Map<String, dynamic> passageDataMap = Map<String, dynamic>.from(passageData as Map);
                final passage = PassageModel.fromJson(passageDataMap);
                passagesToSave.add(passage);
              } catch (e) {
                debugPrint('Erreur lors du traitement d\'un passage: $e');
              }
            }

            if (passagesToSave.isNotEmpty) {
              await passageRepository.savePassages(passagesToSave);
              debugPrint('${passagesToSave.length} passages sauvegardés après UPDATE');
            }
          } catch (e) {
            debugPrint('Erreur lors du traitement des passages: $e');
          }
        } else if ((chkAdressesChange ?? 1) == 0) {
          debugPrint('⏭️ Passages ignorés (chk_adresses_change=0) - les passages existants sont conservés');
        }
        
        // Traiter les users_sectors retournés s'ils existent
        if (responseData['users_sectors'] != null) {
          try {
            final usersSectorsData = responseData['users_sectors'] as List<dynamic>;
            debugPrint('Traitement de ${usersSectorsData.length} associations utilisateur-secteur');
            
            // Sauvegarder les associations dans la box UserSector via DataLoadingService
            await DataLoadingService.instance.processUserSectorsFromApi(usersSectorsData);
            
            for (final userData in usersSectorsData) {
              debugPrint('Utilisateur ${userData['first_name']} ${userData['name']} (ID: ${userData['id']}) assigné au secteur ${userData['fk_sector']}');
            }
          } catch (e) {
            debugPrint('Erreur lors du traitement des users_sectors: $e');
          }
        }
        
        // Afficher les statistiques
        final orphaned = responseData['passages_orphaned'] ?? 0;
        final updated = responseData['passages_updated'] ?? 0;
        final created = responseData['passages_created'] ?? 0;
        final total = responseData['passages_total'] ?? 0;
        debugPrint('Statistiques UPDATE: $orphaned orphelins, $updated mis à jour, $created créés, $total total');
        
        // Retourner toutes les informations
        return {
          'status': 'success',
          'sector': responseData['sector'] != null ? SectorModel.fromJson(responseData['sector']) : null,
          'passages_orphaned': orphaned,
          'passages_updated': updated,
          'passages_created': created,
          'passages_total': total,
          'warning': responseData['warning'],
          'intersecting_departments': responseData['intersecting_departments'],
        };
      }

      return {
        'status': 'error',
        'message': responseData['message'] ?? 'Erreur lors de la mise à jour'
      };
    } catch (e) {
      debugPrint('Erreur lors de la mise à jour du secteur: $e');
      return {
        'status': 'error',
        'message': 'Erreur de connexion au serveur'
      };
    }
  }

  // Supprimer un secteur via l'API
  Future<Map<String, dynamic>> deleteSectorFromApi(int id) async {
    try {
      final response = await ApiService.instance.delete(
        '${AppKeys.sectorsEndpoint}/$id',
      );
      
      // Vérifier si la requête a été mise en queue (mode offline)
      if (response.data != null && response.data['queued'] == true) {
        // Mode offline : Supprimer localement immédiatement
        await _deleteAllPassagesOfSector(id);
        await deleteSector(id);
        debugPrint('⏳ Suppression du secteur $id mise en attente (mode hors ligne)');
        return {
          'status': 'queued',
          'message': 'Suppression mise en attente'
        };
      }
      
      final Map<String, dynamic> responseData = response.data as Map<String, dynamic>;

      if (responseData['status'] == 'success') {
        // 1. Supprimer tous les passages de ce secteur dans Hive
        await _deleteAllPassagesOfSector(id);
        
        // 2. Supprimer le secteur de Hive
        await deleteSector(id);
        
        // 3. Importer les passages orphelins retournés par l'API
        if (responseData['passages_sector'] != null) {
          await _importOrphanPassages(responseData['passages_sector'] as List<dynamic>);
        }
        
        // Vérifier que le secteur a bien été supprimé
        final deletedSector = getSectorById(id);
        if (deletedSector != null) {
          debugPrint('ATTENTION: Le secteur $id existe encore après suppression!');
        } else {
          debugPrint('Secteur $id supprimé avec succès de Hive');
        }
        
        return {
          'status': 'success',
          'passages_deleted': responseData['passages_deleted'] ?? 0,
          'passages_reassigned': responseData['passages_reassigned'] ?? 0,
        };
      }

      return {
        'status': 'error',
        'message': responseData['message'] ?? 'Erreur lors de la suppression',
      };
    } catch (e) {
      debugPrint('Erreur lors de la suppression du secteur: $e');
      return {
        'status': 'error',
        'message': 'Erreur de connexion au serveur',
      };
    }
  }

  // Supprimer tous les passages d'un secteur
  Future<void> _deleteAllPassagesOfSector(int sectorId) async {
    try {
      if (!Hive.isBoxOpen(AppKeys.passagesBoxName)) {
        debugPrint('La boîte des passages n\'est pas ouverte');
        return;
      }
      
      final passagesBox = Hive.box<PassageModel>(AppKeys.passagesBoxName);
      final List<dynamic> keysToDelete = [];
      
      // Identifier toutes les clés des passages du secteur
      for (final entry in passagesBox.toMap().entries) {
        final passage = entry.value;
        if (passage.fkSector == sectorId) {
          keysToDelete.add(entry.key);
        }
      }
      
      if (keysToDelete.isEmpty) {
        debugPrint('Aucun passage à supprimer pour le secteur $sectorId');
        return;
      }
      
      // Supprimer tous les passages en une seule opération
      await passagesBox.deleteAll(keysToDelete);
      
      debugPrint('${keysToDelete.length} passages supprimés du secteur $sectorId en une seule opération');
      
    } catch (e) {
      debugPrint('Erreur lors de la suppression des passages: $e');
    }
  }
  
  // Importer les passages orphelins après suppression d'un secteur
  Future<void> _importOrphanPassages(List<dynamic> passagesData) async {
    try {
      if (passagesData.isEmpty) {
        debugPrint('Aucun passage orphelin à importer');
        return;
      }
      
      final passageRepository = PassageRepository();
      final List<PassageModel> passagesToSave = [];
      
      for (final passageData in passagesData) {
        try {
          // Les passages orphelins ont fk_sector = null
          final Map<String, dynamic> passageDataMap = Map<String, dynamic>.from(passageData as Map);
          final passage = PassageModel.fromJson(passageDataMap);
          passagesToSave.add(passage);
        } catch (e) {
          debugPrint('Erreur lors du traitement d\'un passage orphelin: $e');
        }
      }
      
      if (passagesToSave.isNotEmpty) {
        await passageRepository.savePassages(passagesToSave);
        debugPrint('${passagesToSave.length} passages orphelins importés avec fk_sector = null');
      }
      
    } catch (e) {
      debugPrint('Erreur lors de l\'importation des passages orphelins: $e');
    }
  }
}
