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

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

  // 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<ClientModel> get _clientBox {
    _ensureBoxIsOpen();
    return Hive.box<ClientModel>(AppKeys.clientsBoxName);
  }

  bool _isLoading = false;

  // Getters
  bool get isLoading => _isLoading;
  List<ClientModel> get clients => getAllClients();

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

  // Récupérer tous les clients
  List<ClientModel> getAllClients() {
    return _clientBox.values.toList();
  }

  // Récupérer un client par son ID
  ClientModel? getClientById(int id) {
    return _clientBox.get(id);
  }

  // Sauvegarder un client
  Future<void> saveClient(ClientModel client) async {
    await _clientBox.put(client.id, client);
    notifyListeners();
  }

  // Supprimer un client
  Future<void> deleteClient(int id) async {
    await _clientBox.delete(id);
    notifyListeners();
  }

  // Créer un client via l'API
  Future<bool> createClient(ClientModel client, {BuildContext? context}) async {
    _isLoading = true;
    notifyListeners();

    try {
      // Préparer les données pour l'API - exclure l'id pour la création
      final data = client.toJson();
      data.remove('id'); // L'API génère l'ID
      data.remove('created_at'); // L'API génère created_at
      data.remove('updated_at'); // L'API génère updated_at

      // Appeler l'API pour créer le client
      final response = await ApiService.instance.post('/clients', 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 le client dans Hive
        debugPrint('⏳ Création du client 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 client 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 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 du nouveau client
        final clientId = response.data['id'] is String ? int.parse(response.data['id']) : response.data['id'] as int;

        // Créer le client localement avec l'ID retourné par l'API
        final newClient = client.copyWith(
          createdAt: DateTime.now(),
          updatedAt: DateTime.now(),
        );

        // Sauvegarder avec le nouvel ID
        await _clientBox.put(clientId, newClient);
        notifyListeners();
        return true;
      }
      return false;
    } catch (e) {
      debugPrint('Erreur lors de la création du client: $e');
      return false;
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

  // Mettre à jour un client via l'API
  Future<bool> updateClient(ClientModel client) async {
    _isLoading = true;
    notifyListeners();

    try {
      // Préparer les données pour l'API
      final data = client.toJson();
      // Appeler l'API pour mettre à jour le client
      final response = await ApiService.instance.put('/clients/${client.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 un indicateur
        final updatedClient = client.copyWith(
          updatedAt: DateTime.now(),
          // Note: isSynced n'existe pas dans ClientModel, on utilise updatedAt comme indicateur
        );
        await saveClient(updatedClient);
        debugPrint('⏳ Modification du client ${client.id} mise en attente (mode hors ligne)');
        return true;
      }

      if (response.statusCode == 200) {
        // Mettre à jour le client localement avec updatedAt
        final updatedClient = client.copyWith(
          updatedAt: DateTime.now(),
        );
        await saveClient(updatedClient);
        return true;
      }

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

  // Supprimer un client via l'API
  Future<bool> deleteClientViaApi(int id) async {
    _isLoading = true;
    notifyListeners();

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

      if (response.statusCode == 200 || response.statusCode == 204) {
        // Supprimer le client localement
        await deleteClient(id);
        return true;
      }

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

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

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

      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 de clients non reconnu');
        return;
      }

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

      // Traiter chaque client
      int count = 0;
      for (final clientData in clientsList) {
        try {
          final client = ClientModel.fromJson(clientData);
          await _clientBox.put(client.id, client);
          count++;
        } catch (e) {
          debugPrint('Erreur lors du traitement d\'un client: $e');
        }
      }

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

  // Vider la boîte des clients
  Future<void> clearClients() async {
    await _clientBox.clear();
    notifyListeners();
  }

  // Récupérer les clients depuis l'API
  Future<List<ClientModel>> fetchClientsFromApi() async {
    _isLoading = true;
    notifyListeners();

    try {
      final response = await ApiService.instance.get('/clients');

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

  // === MÉTHODES DE FILTRAGE ET RECHERCHE ===
  // Filtrer les clients par nom
  List<ClientModel> searchClientsByName(String query) {
    if (query.isEmpty) {
      return getAllClients();
    }

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

  // Filtrer les clients par type
  List<ClientModel> getClientsByType(int type) {
    return _clientBox.values.where((client) => client.fkType == type).toList();
  }

  // Filtrer les clients par région
  List<ClientModel> getClientsByRegion(int regionId) {
    return _clientBox.values.where((client) => client.fkRegion == regionId).toList();
  }

  // Filtrer les clients actifs
  List<ClientModel> getActiveClients() {
    return _clientBox.values.where((client) => client.chkActive == true).toList();
  }
}
