import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:path_provider/path_provider.dart';
import 'package:geosector_app/core/constants/app_keys.dart';
import 'package:geosector_app/core/services/hive_web_fix.dart';
import 'package:geosector_app/core/data/models/operation_model.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/data/models/membre_model.dart';
import 'package:geosector_app/core/data/models/user_sector_model.dart';
import 'package:geosector_app/core/data/models/amicale_model.dart';
import 'package:geosector_app/core/repositories/client_repository.dart';
// Chat imports removed - using new simplified chat module
import 'package:geosector_app/core/models/loading_state.dart';

/// Service singleton pour gérer le chargement et la gestion des données au login
class DataLoadingService extends ChangeNotifier {
  static DataLoadingService? _instance;
  static DataLoadingService get instance =>
      _instance ??= DataLoadingService._internal();
  DataLoadingService._internal();

  // État du chargement
  LoadingState _loadingState = LoadingState.initial;
  LoadingState get loadingState => _loadingState;


  // === GETTERS POUR LES BOXES ===
  Box<OperationModel> get _operationBox =>
      Hive.box<OperationModel>(AppKeys.operationsBoxName);
  Box<SectorModel> get _sectorBox =>
      Hive.box<SectorModel>(AppKeys.sectorsBoxName);
  Box<PassageModel> get _passageBox =>
      Hive.box<PassageModel>(AppKeys.passagesBoxName);
  Box<MembreModel> get _membreBox =>
      Hive.box<MembreModel>(AppKeys.membresBoxName);
  Box<UserSectorModel> get _userSectorBox =>
      Hive.box<UserSectorModel>(AppKeys.userSectorBoxName);
  Box<AmicaleModel> get _amicaleBox =>
      Hive.box<AmicaleModel>(AppKeys.amicaleBoxName);
  // Chat boxes removed - handled by new chat module

  /// Traite toutes les données reçues de l'API lors du login
  /// Les boxes sont déjà propres, on charge juste les données
  Future<void> processLoginData(Map<String, dynamic> apiResult) async {
    try {
      debugPrint('📊 Début du chargement des données (boxes déjà propres)...');

      // Vérifier que les boxes sont ouvertes
      _verifyBoxesAreOpen();

      // Charger les données directement (les boxes sont vides et propres)
      if (apiResult['clients'] != null) {
        await _processClients(apiResult['clients']);
      }

      if (apiResult['operations'] != null) {
        await _processOperations(apiResult['operations']);
      }

      if (apiResult['sectors'] != null) {
        await _processSectors(apiResult['sectors']);
      }

      if (apiResult['passages'] != null) {
        await _processPassages(apiResult['passages']);
      }

      if (apiResult['amicale'] != null) {
        await _processAmicale(apiResult['amicale']);
      }
      if (apiResult['membres'] != null) {
        await _processMembres(apiResult['membres']);
      }

      // ATTENTION : L'API envoie 'users_sectors', pas 'userSecteurs'
      if (apiResult['users_sectors'] != null) {
        debugPrint('📋 Traitement des associations users_sectors depuis le login');
        await _processUserSectors(apiResult['users_sectors'], clearAll: true);
      } else if (apiResult['userSecteurs'] != null) {
        // Fallback pour compatibilité si l'API change
        debugPrint('📋 Traitement des associations userSecteurs depuis le login (fallback)');
        await _processUserSectors(apiResult['userSecteurs'], clearAll: true);
      } else {
        debugPrint('⚠️ Aucune donnée users_sectors/userSecteurs trouvée dans la réponse du login');
      }
    } catch (e) {
      debugPrint('❌ Erreur lors du chargement: $e');
      rethrow;
    }
  }

  void _verifyBoxesAreOpen() {
    final requiredBoxes = [
      AppKeys.operationsBoxName,
      AppKeys.sectorsBoxName,
      AppKeys.passagesBoxName,
      AppKeys.membresBoxName,
      AppKeys.userSectorBoxName,
      AppKeys.amicaleBoxName,
    ];

    for (final boxName in requiredBoxes) {
      if (!Hive.isBoxOpen(boxName)) {
        throw Exception(
            'La boîte $boxName n\'est pas ouverte. Redémarrez l\'application.');
      }
    }

    debugPrint('✅ Toutes les boîtes requises sont ouvertes');
  }

  /// Nettoie complètement toutes les données lors du logout
  Future<void> cleanDataAfterLogout() async {
    try {
      debugPrint('🧹 Début du nettoyage complet après logout...');
      await _deepCleanHiveBoxes();
      debugPrint('✅ Nettoyage complet terminé');
    } catch (e) {
      debugPrint('❌ Erreur lors du nettoyage après logout: $e');
      rethrow;
    }
  }

  // === MÉTHODES PUBLIQUES POUR TRAITEMENT EXTERNE ===

  /// Méthode publique pour traiter les secteurs depuis l'extérieur
  Future<void> processSectorsFromApi(dynamic sectorsData) async {
    await _processSectors(sectorsData);
  }

  /// Méthode publique pour traiter les passages depuis l'extérieur
  Future<void> processPassagesFromApi(dynamic passagesData) async {
    await _processPassages(passagesData);
  }

  /// Méthode publique pour traiter les associations user-sectors depuis l'extérieur
  /// [clearAll] : si true, vide toute la box avant d'ajouter (pour le login)
  ///              si false, ne supprime que les secteurs concernés (pour les mises à jour)
  Future<void> processUserSectorsFromApi(dynamic userSectorsData, {bool clearAll = false}) async {
    await _processUserSectors(userSectorsData, clearAll: clearAll);
  }

  /// Méthode publique pour traiter les opérations depuis l'extérieur
  Future<void> processOperationsFromApi(dynamic operationsData) async {
    await _processOperations(operationsData);
  }

  // === MÉTHODES DE TRAITEMENT DES DONNÉES ===

  Future<void> _processClients(dynamic clientsData) async {
    try {
      debugPrint('👥 Traitement des clients...');

      List<dynamic> clientsList;
      if (clientsData is List) {
        clientsList = clientsData;
      } else if (clientsData is Map && clientsData.containsKey('data')) {
        clientsList = clientsData['data'] as List<dynamic>;
      } else {
        debugPrint('⚠️ Format de données clients non reconnu');
        return;
      }

      if (clientsList.isNotEmpty) {
        debugPrint('📊 Traitement de ${clientsList.length} clients de type 1');
        final clientRepository = ClientRepository();
        await clientRepository.processClientsData(clientsList);
        debugPrint('✅ Clients traités via ClientRepository');
      }
    } catch (e) {
      debugPrint('❌ Erreur traitement clients: $e');
    }
  }

  Future<void> _processOperations(dynamic operationsData) async {
    try {
      debugPrint('⚙️ Traitement des opérations...');

      if (operationsData == null) {
        debugPrint('ℹ️ Aucune donnée d\'opération à traiter');
        return;
      }

      List<dynamic> operationsList;
      if (operationsData is List) {
        operationsList = operationsData;
      } else if (operationsData is Map && operationsData.containsKey('data')) {
        operationsList = operationsData['data'] as List<dynamic>;
      } else {
        debugPrint('⚠️ Format de données d\'opérations non reconnu');
        return;
      }

      await _operationBox.clear();

      int count = 0;
      for (final operationData in operationsList) {
        try {
          final operation = OperationModel.fromJson(operationData);
          await _operationBox.put(operation.id, operation);
          count++;
        } catch (e) {
          debugPrint('⚠️ Erreur traitement opération: $e');
        }
      }

      debugPrint('✅ $count opérations stockées');
    } catch (e) {
      debugPrint('❌ Erreur traitement opérations: $e');
    }
  }

  Future<void> _processSectors(dynamic sectorsData) async {
    try {
      debugPrint('📍 Traitement des secteurs...');

      if (sectorsData == null) {
        debugPrint('ℹ️ Aucune donnée de secteur à traiter');
        return;
      }

      List<dynamic> sectorsList;
      if (sectorsData is List) {
        sectorsList = sectorsData;
        debugPrint('📋 ${sectorsList.length} secteurs à traiter (format: List directe)');
      } else if (sectorsData is Map && sectorsData.containsKey('data')) {
        sectorsList = sectorsData['data'] as List<dynamic>;
        debugPrint('📋 ${sectorsList.length} secteurs à traiter (format: Map avec data)');
      } else {
        debugPrint('⚠️ Format de données de secteurs non reconnu: ${sectorsData.runtimeType}');
        debugPrint('⚠️ Contenu: ${sectorsData.toString().substring(0, 200)}...');
        return;
      }

      await _sectorBox.clear();

      int count = 0;
      int errorCount = 0;
      for (final sectorData in sectorsList) {
        try {
          debugPrint('🔄 Traitement secteur ID: ${sectorData['id']}, libelle: "${sectorData['libelle']}"');
          final sector = SectorModel.fromJson(sectorData);
          await _sectorBox.put(sector.id, sector);
          count++;
        } catch (e) {
          errorCount++;
          debugPrint('⚠️ Erreur traitement secteur ${sectorData['id']}: $e');
          debugPrint('⚠️ Données problématiques: $sectorData');
        }
      }

      debugPrint('✅ $count secteurs stockés${errorCount > 0 ? ' ($errorCount erreurs ignorées)' : ''}');
      
      // Vérification finale
      final storedSectors = _sectorBox.values.toList();
      debugPrint('🔍 Vérification: ${storedSectors.length} secteurs dans la box');
      for (final sector in storedSectors) {
        debugPrint('   - Secteur ${sector.id}: "${sector.libelle}" (${sector.color})');
      }
    } catch (e) {
      debugPrint('❌ Erreur traitement secteurs: $e');
    }
  }

  Future<void> _processPassages(dynamic passagesData) async {
    try {
      debugPrint('🚶 Traitement des passages...');

      if (passagesData == null) {
        debugPrint('ℹ️ Aucune donnée de passage à traiter');
        return;
      }

      List<dynamic> passagesList;
      if (passagesData is List) {
        passagesList = passagesData;
      } else if (passagesData is Map && passagesData.containsKey('data')) {
        passagesList = passagesData['data'] as List<dynamic>;
      } else {
        debugPrint('⚠️ Format de données de passages non reconnu');
        return;
      }

      await _passageBox.clear();

      int count = 0;
      int errorCount = 0;
      for (final passageData in passagesList) {
        try {
          final passage = PassageModel.fromJson(passageData);
          await _passageBox.put(passage.id, passage);
          count++;
        } catch (e) {
          errorCount++;
          debugPrint('⚠️ Erreur traitement passage ${passageData['id']}: $e');
          // Continue avec le passage suivant au lieu de s'arrêter
        }
      }

      debugPrint(
          '✅ $count passages stockés${errorCount > 0 ? ' ($errorCount erreurs ignorées)' : ''}');
    } catch (e) {
      debugPrint('❌ Erreur traitement passages: $e');
    }
  }

  // Ajouter cette nouvelle méthode pour traiter l'amicale unique
  Future<void> _processAmicale(dynamic amicaleData) async {
    try {
      debugPrint('🏢 Traitement de l\'amicale unique...');

      if (amicaleData == null) {
        debugPrint('ℹ️ Aucune donnée d\'amicale à traiter');
        return;
      }

      await _amicaleBox.clear();
      try {
        // Les données d'amicale sont un objet unique
        final Map<String, dynamic> amicaleMap =
            Map<String, dynamic>.from(amicaleData as Map);
        final amicale = AmicaleModel.fromJson(amicaleMap);
        await _amicaleBox.put(amicale.id, amicale);
        debugPrint('✅ Amicale stockée: ${amicale.name} (ID: ${amicale.id})');
      } catch (e) {
        debugPrint('⚠️ Erreur traitement amicale: $e');
        debugPrint('⚠️ Données reçues: $amicaleData');
      }
    } catch (e) {
      debugPrint('❌ Erreur traitement amicale: $e');
    }
  }

  Future<void> _processMembres(dynamic membresData) async {
    try {
      debugPrint('👤 Traitement des membres...');

      if (membresData == null) {
        debugPrint('ℹ️ Aucune donnée de membre à traiter');
        return;
      }

      List<dynamic> membresList;
      if (membresData is List) {
        membresList = membresData;
      } else if (membresData is Map && membresData.containsKey('data')) {
        membresList = membresData['data'] as List<dynamic>;
      } else {
        debugPrint('⚠️ Format de données de membres non reconnu');
        return;
      }

      await _membreBox.clear();

      int count = 0;
      int errorCount = 0;
      for (final membreData in membresList) {
        try {
          final membre = MembreModel.fromJson(membreData);
          await _membreBox.put(membre.id, membre);
          count++;
        } catch (e) {
          errorCount++;
          debugPrint('⚠️ Erreur traitement membre ${membreData['id']}: $e');
          // Continue avec le membre suivant au lieu de s'arrêter
        }
      }

      debugPrint(
          '✅ $count membres stockés${errorCount > 0 ? ' ($errorCount erreurs ignorées)' : ''}');
    } catch (e) {
      debugPrint('❌ Erreur traitement membres: $e');
    }
  }

  Future<void> _processUserSectors(dynamic userSectorsData, {bool clearAll = false}) async {
    try {
      debugPrint('🔗 Traitement des associations utilisateurs-secteurs...');
      debugPrint('Type de données reçues: ${userSectorsData.runtimeType}');

      if (userSectorsData == null) {
        debugPrint('ℹ️ Aucune association utilisateur-secteur à traiter');
        return;
      }

      List<dynamic> userSectorsList;
      if (userSectorsData is List) {
        userSectorsList = userSectorsData;
        debugPrint('✅ Données au format List avec ${userSectorsList.length} éléments');
      } else if (userSectorsData is Map &&
          userSectorsData.containsKey('data')) {
        userSectorsList = userSectorsData['data'] as List<dynamic>;
        debugPrint('✅ Données au format Map[data] avec ${userSectorsList.length} éléments');
      } else {
        debugPrint('⚠️ Format de données d\'associations non reconnu');
        return;
      }

      // Vérifier si la box est ouverte
      if (!Hive.isBoxOpen(AppKeys.userSectorBoxName)) {
        debugPrint('❌ La box UserSector n\'est pas ouverte!');
        return;
      }

      if (clearAll) {
        // Mode login : on vide toute la box
        await _userSectorBox.clear();
        debugPrint('📦 Box UserSector vidée complètement (mode login)');
      } else {
        // Mode mise à jour : on ne supprime que les associations des secteurs concernés
        // car l'API ne retourne que les associations pour le(s) secteur(s) modifié(s)
        
        // Identifier les secteurs concernés dans les nouvelles données
        final Set<int> sectorsToUpdate = {};
        for (final data in userSectorsList) {
          if (data['fk_sector'] != null) {
            final fkSector = data['fk_sector'] is String 
                ? int.parse(data['fk_sector']) 
                : data['fk_sector'] as int;
            sectorsToUpdate.add(fkSector);
          }
        }
        
        // Supprimer uniquement les associations des secteurs concernés
        if (sectorsToUpdate.isNotEmpty) {
          debugPrint('🗑️ Suppression des associations pour les secteurs: $sectorsToUpdate');
          final keysToDelete = <dynamic>[];
          
          for (var i = 0; i < _userSectorBox.length; i++) {
            final key = _userSectorBox.keyAt(i);
            final userSector = _userSectorBox.getAt(i);
            if (userSector != null && sectorsToUpdate.contains(userSector.fkSector)) {
              keysToDelete.add(key);
            }
          }
          
          for (final key in keysToDelete) {
            await _userSectorBox.delete(key);
          }
          
          debugPrint('📦 ${keysToDelete.length} associations supprimées');
        }
      }

      int count = 0;
      for (final userSectorData in userSectorsList) {
        try {
          final userSector = UserSectorModel.fromJson(userSectorData);
          final key = '${userSector.opeUserId}_${userSector.fkSector}';
          await _userSectorBox.put(key, userSector);
          debugPrint('✅ Association sauvegardée: ${userSector.firstName} ${userSector.name} (userId: ${userSector.userId}, opeUserId: ${userSector.opeUserId}) -> Secteur ${userSector.fkSector}');
          count++;
        } catch (e) {
          debugPrint('⚠️ Erreur traitement association: $e');
          debugPrint('⚠️ Données problématiques: $userSectorData');
        }
      }

      debugPrint('✅ $count associations stockées');
      
      // Vérifier le contenu de la box après sauvegarde
      debugPrint('📦 Contenu de la box UserSector après sauvegarde:');
      debugPrint('   - Nombre d\'entrées: ${_userSectorBox.length}');
      for (var i = 0; i < _userSectorBox.length && i < 5; i++) {
        final key = _userSectorBox.keyAt(i);
        final value = _userSectorBox.getAt(i);
        if (value != null) {
          debugPrint('   - [$key]: ${value.firstName} ${value.name} (userId: ${value.userId}, opeUserId: ${value.opeUserId}) -> Secteur ${value.fkSector}');
        }
      }
      if (_userSectorBox.length > 5) {
        debugPrint('   ... et ${_userSectorBox.length - 5} autres associations');
      }
    } catch (e) {
      debugPrint('❌ Erreur traitement associations: $e');
    }
  }

  // === MÉTHODES DE NETTOYAGE PLATEFORME SPÉCIFIQUES ===

  Future<void> _cleanHiveFilesOnIOS() async {
    if (!kIsWeb && Platform.isIOS) {
      try {
        debugPrint('🍎 Nettoyage des fichiers Hive sur iOS...');
        final appDir = await getApplicationDocumentsDirectory();
        final hiveDir = Directory('${appDir.path}/hive');

        if (await hiveDir.exists()) {
          final entries = await hiveDir.list().toList();
          for (var entry in entries) {
            final name = entry.path.split('/').last;
            if (!name.contains(AppKeys.userBoxName)) {
              if (entry is Directory) {
                await entry.delete(recursive: true);
              } else if (entry is File) {
                await entry.delete();
              }
            }
          }
          debugPrint('✅ Nettoyage iOS terminé');
        }
      } catch (e) {
        debugPrint('❌ Erreur nettoyage iOS: $e');
      }
    }
  }

  Future<void> _cleanHiveFilesOnAndroid() async {
    if (!kIsWeb && Platform.isAndroid) {
      try {
        debugPrint('🤖 Nettoyage des fichiers Hive sur Android...');
        final appDir = await getApplicationDocumentsDirectory();
        final entries = await appDir.list().toList();
        int filesDeleted = 0;

        for (var entry in entries) {
          final name = entry.path.split('/').last;
          if (name.endsWith('.hive') && !name.contains(AppKeys.userBoxName)) {
            if (entry is File) {
              await entry.delete();
              filesDeleted++;

              final lockFile = File('${entry.path}.lock');
              if (await lockFile.exists()) {
                await lockFile.delete();
              }
            }
          }
        }

        debugPrint(
            '✅ Nettoyage Android terminé. $filesDeleted fichiers supprimés');
      } catch (e) {
        debugPrint('❌ Erreur nettoyage Android: $e');
      }
    }
  }

  Future<void> _deepCleanHiveBoxes() async {
    try {
      debugPrint('🧹 Nettoyage profond des boîtes Hive...');

      // Vider toutes les boîtes
      final boxesToClean = [
        AppKeys.operationsBoxName,
        AppKeys.sectorsBoxName,
        AppKeys.passagesBoxName,
        AppKeys.membresBoxName,
        AppKeys.userSectorBoxName,
        AppKeys.amicaleBoxName,
        AppKeys.chatRoomsBoxName,
        AppKeys.chatMessagesBoxName,
        AppKeys.settingsBoxName,
      ];

      for (final boxName in boxesToClean) {
        try {
          if (Hive.isBoxOpen(boxName)) {
            await Hive.box(boxName).clear();
            debugPrint('✅ Box $boxName vidée');
          }
        } catch (e) {
          debugPrint('⚠️ Erreur vidage box $boxName: $e');
        }
      }

      // Nettoyage spécifique à la plateforme
      if (kIsWeb) {
        await HiveWebFix.resetHiveCompletely();
      } else if (Platform.isIOS) {
        await _cleanHiveFilesOnIOS();
      } else if (Platform.isAndroid) {
        await _cleanHiveFilesOnAndroid();
      }

      await Future.delayed(const Duration(milliseconds: 800));
      debugPrint('✅ Nettoyage profond terminé');
    } catch (e) {
      debugPrint('❌ Erreur nettoyage profond: $e');
    }
  }

  // === RESET POUR TESTS ===
  static void reset() {
    _instance = null;
  }
}
