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

class AmicaleRepository extends ChangeNotifier {
  // Constructeur sans paramètres - utilise ApiService.instance
  AmicaleRepository();

  // Utiliser un getter lazy pour n'accéder à la boîte que lorsque nécessaire
  // et vérifier qu'elle est ouverte avant accès
  Box<AmicaleModel> get _amicaleBox {
    _ensureBoxIsOpen();
    return Hive.box<AmicaleModel>(AppKeys.amicaleBoxName);
  }

  bool _isLoading = false;

  // Getters
  bool get isLoading => _isLoading;
  List<AmicaleModel> get amicales => getAllAmicales();

  // Méthode pour vérifier si la boîte est ouverte et l'ouvrir si nécessaire
  Future<void> _ensureBoxIsOpen() async {
    const boxName = AppKeys.amicaleBoxName;
    if (!Hive.isBoxOpen(boxName)) {
      debugPrint('Ouverture de la boîte $boxName dans AmicaleRepository...');
      await Hive.openBox<AmicaleModel>(boxName);
    }
  }

  // Méthode pour exposer la Box Hive (nécessaire pour ValueListenableBuilder)
  Box<AmicaleModel> getAmicalesBox() {
    try {
      if (!Hive.isBoxOpen(AppKeys.amicaleBoxName)) {
        throw Exception('La boîte amicales n\'est pas ouverte');
      }
      return _amicaleBox;
    } catch (e) {
      debugPrint('Erreur lors de l\'accès à la boîte amicales: $e');
      rethrow;
    }
  }

  // Récupérer toutes les amicales
  List<AmicaleModel> getAllAmicales() {
    return _amicaleBox.values.toList();
  }

  // Récupérer une amicale par son ID
  AmicaleModel? getAmicaleById(int id) {
    return _amicaleBox.get(id);
  }

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

  // Récupérer uniquement les clients (type 1)
  List<AmicaleModel> getClients() {
    return getAmicalesByType(1);
  }

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

  // Sauvegarder une amicale
  Future<void> saveAmicale(AmicaleModel amicale) async {
    await _amicaleBox.put(amicale.id, amicale);
    notifyListeners();
  }

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

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

  // Créer une amicale via l'API
  Future<bool> createAmicale(AmicaleModel amicale, {BuildContext? context}) async {
    _isLoading = true;
    notifyListeners();

    try {
      // Préparer les données pour l'API
      final data = amicale.toJson();

      // Appeler l'API pour créer l'amicale
      final response = await ApiService.instance.post('/amicales', data: data);

      // 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 l'amicale dans Hive
        debugPrint('⏳ Création de l\'amicale 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(
                'L\'amicale sera créée 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 true; // Indiquer que l'opération a été acceptée (mise en queue)
      }

      if (response.statusCode == 201 || response.statusCode == 200) {
        // Récupérer l'ID de la nouvelle amicale
        final amicaleId = response.data['id'] is String ? int.parse(response.data['id']) : response.data['id'] as int;

        // Créer l'amicale localement avec l'ID retourné par l'API et updatedAt
        final amicaleWithNewId = AmicaleModel(
          id: amicaleId,
          name: amicale.name,
          adresse1: amicale.adresse1,
          adresse2: amicale.adresse2,
          codePostal: amicale.codePostal,
          ville: amicale.ville,
          fkRegion: amicale.fkRegion,
          libRegion: amicale.libRegion,
          fkType: amicale.fkType,
          phone: amicale.phone,
          mobile: amicale.mobile,
          email: amicale.email,
          gpsLat: amicale.gpsLat,
          gpsLng: amicale.gpsLng,
          stripeId: amicale.stripeId,
          chkDemo: amicale.chkDemo,
          chkCopieMailRecu: amicale.chkCopieMailRecu,
          chkAcceptSms: amicale.chkAcceptSms,
          chkActive: amicale.chkActive,
          chkStripe: amicale.chkStripe,
          chkMdpManuel: amicale.chkMdpManuel,
          chkUsernameManuel: amicale.chkUsernameManuel,
          chkUserDeletePass: amicale.chkUserDeletePass,
          chkLotActif: amicale.chkLotActif,
          createdAt: amicale.createdAt ?? DateTime.now(),
          updatedAt: DateTime.now(),
        );

        await saveAmicale(amicaleWithNewId);
        return true;
      }

      return false;
    } catch (e) {
      debugPrint('Erreur lors de la création de l\'amicale: $e');
      return false;
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

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

    try {
      // Préparer les données pour l'API
      final data = amicale.toJson();

      // Appeler l'API pour mettre à jour l'amicale
      final response = await ApiService.instance.put('/amicales/${amicale.id}', data: data);

      // 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
        final updatedAmicale = amicale.copyWith(
          updatedAt: DateTime.now(),
        );
        await saveAmicale(updatedAmicale);
        debugPrint('⏳ Modification de l\'amicale ${amicale.id} mise en attente (mode hors ligne)');
        return true;
      }

      if (response.statusCode == 200) {
        // Mettre à jour l'amicale localement avec updatedAt
        final updatedAmicale = amicale.copyWith(
          updatedAt: DateTime.now(),
        );

        await saveAmicale(updatedAmicale);
        return true;
      }

      return false;
    } catch (e) {
      debugPrint('Erreur lors de la mise à jour de l\'amicale: $e');
      return false;
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

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

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

      // 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
        await saveAmicale(amicale);
        debugPrint('⏳ Modification de l\'amicale ${amicale.id} mise en attente (mode hors ligne)');
        return amicale; // Retourner l'amicale locale
      }

      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();
    }
  }

  // Supprimer une amicale via l'API
  Future<bool> deleteAmicaleViaApi(int id) async {
    _isLoading = true;
    notifyListeners();

    try {
      // Appeler l'API pour supprimer l'amicale
      final response = await ApiService.instance.delete('/amicales/$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 deleteAmicale(id);
        debugPrint('⏳ Suppression de l\'amicale $id mise en attente (mode hors ligne)');
        return true;
      }

      if (response.statusCode == 200 || response.statusCode == 204) {
        // Supprimer l'amicale localement
        await deleteAmicale(id);
        return true;
      }

      return false;
    } catch (e) {
      debugPrint('Erreur lors de la suppression de l\'amicale: $e');
      return false;
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

  // Traitement des données d'amicale depuis l'API (amicale unique)
  Future<void> processAmicalesData(dynamic amicaleData) async {
    try {
      debugPrint('Traitement de l\'amicale utilisateur...');

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

      // Vider la boîte avant d'ajouter la nouvelle amicale
      await _amicaleBox.clear();

      try {
        // Les données sont un objet amicale 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 utilisateur traitée: ${amicale.name} (ID: ${amicale.id})');
        notifyListeners();
      } catch (e) {
        debugPrint('❌ Erreur lors du traitement de l\'amicale: $e');
        debugPrint('Données reçues: $amicaleData');
      }
    } catch (e) {
      debugPrint('❌ Erreur lors du traitement de l\'amicale: $e');
    }
  }

// Méthode spécifique pour récupérer l'amicale de l'utilisateur connecté
  AmicaleModel? getUserAmicale(int fkEntite) {
    try {
      final amicale = _amicaleBox.get(fkEntite);
      debugPrint('🔍 Recherche amicale ID $fkEntite: ${amicale?.name ?? 'non trouvée'}');
      return amicale;
    } catch (e) {
      debugPrint('❌ Erreur lors de la récupération de l\'amicale utilisateur: $e');
      return null;
    }
  }

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

    try {
      final response = await ApiService.instance.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.instance.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();
    }
  }

  // === MÉTHODES DE FILTRAGE ET RECHERCHE ===

  // 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 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();
  }
}
