import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:geosector_app/core/constants/app_keys.dart';
import 'package:geosector_app/core/services/api_service.dart';
import 'package:geosector_app/core/data/models/amicale_model.dart';

class AmicaleRepository extends ChangeNotifier {
  // Utilisation de getters lazy pour n'accéder à la boîte que lorsque nécessaire
  Box<AmicaleModel> get _amicaleBox =>
      Hive.box<AmicaleModel>(AppKeys.amicaleBoxName);

  final ApiService _apiService;
  bool _isLoading = false;

  AmicaleRepository(this._apiService);

  // Getters
  bool get isLoading => _isLoading;

  // Méthode pour vérifier si une boîte est ouverte et l'ouvrir si nécessaire
  Future<void> _ensureBoxIsOpen() async {
    try {
      if (!Hive.isBoxOpen(AppKeys.amicaleBoxName)) {
        debugPrint('Ouverture de la boîte amicale...');
        await Hive.openBox<AmicaleModel>(AppKeys.amicaleBoxName);
      }
    } catch (e) {
      debugPrint('Erreur lors de l\'ouverture de la boîte amicale: $e');
      throw Exception('Impossible d\'ouvrir la boîte amicale: $e');
    }
  }

  // Récupérer toutes les amicales
  List<AmicaleModel> getAllAmicales() {
    try {
      _ensureBoxIsOpen();
      return _amicaleBox.values.toList();
    } catch (e) {
      debugPrint('Erreur lors de la récupération des amicales: $e');
      return [];
    }
  }

  // Récupérer une amicale par son ID
  AmicaleModel? getAmicaleById(int id) {
    try {
      _ensureBoxIsOpen();
      return _amicaleBox.get(id);
    } catch (e) {
      debugPrint('Erreur lors de la récupération de l\'amicale: $e');
      return null;
    }
  }

  // Récupérer l'amicale de l'utilisateur connecté (basé sur fkEntite)
  AmicaleModel? getAmicaleByUserId(int userId, int fkEntite) {
    try {
      _ensureBoxIsOpen();
      return _amicaleBox.get(fkEntite);
    } catch (e) {
      debugPrint(
          'Erreur lors de la récupération de l\'amicale de l\'utilisateur: $e');
      return null;
    }
  }

  // Créer ou mettre à jour une amicale localement
  Future<AmicaleModel> saveAmicale(AmicaleModel amicale) async {
    await _ensureBoxIsOpen();
    await _amicaleBox.put(amicale.id, amicale);
    notifyListeners(); // Notifier les changements pour mettre à jour l'UI
    return amicale;
  }

  // Supprimer une amicale localement
  Future<void> deleteAmicale(int id) async {
    await _ensureBoxIsOpen();
    await _amicaleBox.delete(id);
    notifyListeners();
  }

  // Vider la boîte des amicales
  Future<void> clearAmicales() async {
    await _ensureBoxIsOpen();
    await _amicaleBox.clear();
    notifyListeners();
  }

  // Traiter les données des amicales reçues de l'API
  Future<void> processAmicalesData(dynamic amicalesData) async {
    try {
      debugPrint('Traitement des données des amicales...');
      debugPrint('Détails amicale: $amicalesData');

      // Vérifier que les données sont au bon format
      if (amicalesData == null) {
        debugPrint('Aucune donnée d\'amicale à traiter');
        return;
      }

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

      int count = 0;

      // Cas 1: Les données sont une liste d'amicales
      if (amicalesData is List) {
        for (final amicaleData in amicalesData) {
          try {
            final amicale = AmicaleModel.fromJson(amicaleData);
            await _amicaleBox.put(amicale.id, amicale);
            count++;
            debugPrint('Amicale traitée: ${amicale.name} (ID: ${amicale.id})');
          } catch (e) {
            debugPrint('Erreur lors du traitement d\'une amicale: $e');
          }
        }
      }
      // Cas 2: Les données sont un objet avec une clé 'data' contenant une liste
      else if (amicalesData is Map && amicalesData.containsKey('data')) {
        final amicalesList = amicalesData['data'] as List<dynamic>;
        for (final amicaleData in amicalesList) {
          try {
            final amicale = AmicaleModel.fromJson(amicaleData);
            await _amicaleBox.put(amicale.id, amicale);
            count++;
            debugPrint('Amicale traitée: ${amicale.name} (ID: ${amicale.id})');
          } catch (e) {
            debugPrint('Erreur lors du traitement d\'une amicale: $e');
          }
        }
      }
      // Cas 3: Les données sont un objet amicale unique (pas une liste)
      else if (amicalesData is Map) {
        try {
          // Convertir Map<dynamic, dynamic> en Map<String, dynamic>
          final Map<String, dynamic> amicaleMap = {};
          amicalesData.forEach((key, value) {
            if (key is String) {
              amicaleMap[key] = value;
            }
          });

          final amicale = AmicaleModel.fromJson(amicaleMap);
          await _amicaleBox.put(amicale.id, amicale);
          count++;
          debugPrint(
              'Amicale unique traitée: ${amicale.name} (ID: ${amicale.id})');
        } catch (e) {
          debugPrint('Erreur lors du traitement de l\'amicale unique: $e');
          debugPrint('Exception détaillée: $e');
        }
      } else {
        debugPrint('Format de données d\'amicale non reconnu');
        return;
      }

      debugPrint('$count amicales traitées et stockées');
      notifyListeners();
    } catch (e) {
      debugPrint('Erreur lors du traitement des amicales: $e');
    }
  }

  // Récupérer les amicales depuis l'API
  Future<List<AmicaleModel>> fetchAmicalesFromApi() async {
    _isLoading = true;
    notifyListeners();

    try {
      final response = await _apiService.get('/amicales');

      if (response.statusCode == 200) {
        final amicalesData = response.data;
        await processAmicalesData(amicalesData);
        return getAllAmicales();
      } else {
        debugPrint(
            'Erreur lors de la récupération des amicales: ${response.statusCode}');
        return [];
      }
    } catch (e) {
      debugPrint('Erreur lors de la récupération des amicales: $e');
      return [];
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

  // Récupérer une amicale spécifique depuis l'API
  Future<AmicaleModel?> fetchAmicaleByIdFromApi(int id) async {
    _isLoading = true;
    notifyListeners();

    try {
      final response = await _apiService.get('/amicales/$id');

      if (response.statusCode == 200) {
        final amicaleData = response.data;
        final amicale = AmicaleModel.fromJson(amicaleData);
        await saveAmicale(amicale);
        return amicale;
      } else {
        debugPrint(
            'Erreur lors de la récupération de l\'amicale: ${response.statusCode}');
        return null;
      }
    } catch (e) {
      debugPrint('Erreur lors de la récupération de l\'amicale: $e');
      return null;
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

  // Mettre à jour une amicale via l'API
  Future<AmicaleModel?> updateAmicaleViaApi(AmicaleModel amicale) async {
    _isLoading = true;
    notifyListeners();

    try {
      final response = await _apiService.put(
        '/amicales/${amicale.id}',
        data: amicale.toJson(),
      );

      if (response.statusCode == 200) {
        final updatedAmicaleData = response.data;
        final updatedAmicale = AmicaleModel.fromJson(updatedAmicaleData);
        await saveAmicale(updatedAmicale);
        return updatedAmicale;
      } else {
        debugPrint(
            'Erreur lors de la mise à jour de l\'amicale: ${response.statusCode}');
        return null;
      }
    } catch (e) {
      debugPrint('Erreur lors de la mise à jour de l\'amicale: $e');
      return null;
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

  // Filtrer les amicales par nom
  List<AmicaleModel> searchAmicalesByName(String query) {
    if (query.isEmpty) {
      return getAllAmicales();
    }

    final lowercaseQuery = query.toLowerCase();
    return _amicaleBox.values
        .where((amicale) => amicale.name.toLowerCase().contains(lowercaseQuery))
        .toList();
  }

  // Filtrer les amicales par type
  List<AmicaleModel> getAmicalesByType(int type) {
    return _amicaleBox.values
        .where((amicale) => amicale.fkType == type)
        .toList();
  }

  // Filtrer les amicales par région
  List<AmicaleModel> getAmicalesByRegion(int regionId) {
    return _amicaleBox.values
        .where((amicale) => amicale.fkRegion == regionId)
        .toList();
  }

  // Filtrer les amicales actives
  List<AmicaleModel> getActiveAmicales() {
    return _amicaleBox.values.where((amicale) => amicale.chkActive).toList();
  }

  // Filtrer les amicales par code postal
  List<AmicaleModel> getAmicalesByPostalCode(String postalCode) {
    return _amicaleBox.values
        .where((amicale) => amicale.codePostal == postalCode)
        .toList();
  }

  // Filtrer les amicales par ville
  List<AmicaleModel> getAmicalesByCity(String city) {
    final lowercaseCity = city.toLowerCase();
    return _amicaleBox.values
        .where((amicale) => amicale.ville.toLowerCase().contains(lowercaseCity))
        .toList();
  }
}
