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

class OperationRepository extends ChangeNotifier {
  // 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<OperationModel> get _operationBox {
    _ensureBoxIsOpen();
    return Hive.box<OperationModel>(AppKeys.operationsBoxName);
  }
  
  // Méthode pour vérifier si la boîte est ouverte et l'ouvrir si nécessaire
  Future<void> _ensureBoxIsOpen() async {
    final boxName = AppKeys.operationsBoxName;
    if (!Hive.isBoxOpen(boxName)) {
      debugPrint('Ouverture de la boîte $boxName dans OperationRepository...');
      await Hive.openBox<OperationModel>(boxName);
    }
  }
  final ApiService _apiService;

  bool _isLoading = false;

  OperationRepository(this._apiService);

  // Getters
  bool get isLoading => _isLoading;
  List<OperationModel> get operations => getAllOperations();

  // Récupérer toutes les opérations
  List<OperationModel> getAllOperations() {
    return _operationBox.values.toList();
  }

  // Récupérer une opération par son ID
  OperationModel? getOperationById(int id) {
    return _operationBox.get(id);
  }

  // Sauvegarder une opération
  Future<void> saveOperation(OperationModel operation) async {
    await _operationBox.put(operation.id, operation);
    notifyListeners();
  }

  // Supprimer une opération
  Future<void> deleteOperation(int id) async {
    await _operationBox.delete(id);
    notifyListeners();
  }

  // Créer ou mettre à jour des opérations à partir des données de l'API
  Future<void> processOperationsFromApi(List<dynamic> operationsData) async {
    _isLoading = true;
    notifyListeners();

    try {
      for (var operationData in operationsData) {
        final operationJson = operationData as Map<String, dynamic>;
        final operationId = operationJson['id'] is String 
            ? int.parse(operationJson['id']) 
            : operationJson['id'] as int;
        
        // Vérifier si l'opération existe déjà
        OperationModel? existingOperation = getOperationById(operationId);
        
        if (existingOperation == null) {
          // Créer une nouvelle opération
          final newOperation = OperationModel.fromJson(operationJson);
          await saveOperation(newOperation);
        } else {
          // Mettre à jour l'opération existante
          final updatedOperation = existingOperation.copyWith(
            name: operationJson['name'],
            dateDebut: DateTime.parse(operationJson['date_deb']),
            dateFin: DateTime.parse(operationJson['date_fin']),
            lastSyncedAt: DateTime.now(),
            isSynced: true,
          );
          await saveOperation(updatedOperation);
        }
      }
    } catch (e) {
      debugPrint('Erreur lors du traitement des opérations: $e');
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

  // Créer une opération
  Future<bool> createOperation(String name, DateTime dateDebut, DateTime dateFin) async {
    _isLoading = true;
    notifyListeners();

    try {
      // Préparer les données pour l'API
      final Map<String, dynamic> data = {
        'name': name,
        'date_deb': dateDebut.toIso8601String().split('T')[0], // Format YYYY-MM-DD
        'date_fin': dateFin.toIso8601String().split('T')[0], // Format YYYY-MM-DD
      };

      // Appeler l'API pour créer l'opération
      final response = await _apiService.post('/operations', data: data);
      
      if (response.statusCode == 201 || response.statusCode == 200) {
        // Récupérer l'ID de la nouvelle opération
        final operationId = response.data['id'] is String 
            ? int.parse(response.data['id']) 
            : response.data['id'] as int;
        
        // Créer l'opération localement
        final newOperation = OperationModel(
          id: operationId,
          name: name,
          dateDebut: dateDebut,
          dateFin: dateFin,
          lastSyncedAt: DateTime.now(),
          isActive: true,
          isSynced: true,
        );
        
        await saveOperation(newOperation);
        return true;
      }
      
      return false;
    } catch (e) {
      debugPrint('Erreur lors de la création de l\'opération: $e');
      return false;
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

  // Mettre à jour une opération
  Future<bool> updateOperation(int id, {String? name, DateTime? dateDebut, DateTime? dateFin, bool? isActive}) async {
    _isLoading = true;
    notifyListeners();

    try {
      // Récupérer l'opération existante
      final existingOperation = getOperationById(id);
      if (existingOperation == null) {
        return false;
      }

      // Préparer les données pour l'API
      final Map<String, dynamic> data = {
        'id': id,
        'name': name ?? existingOperation.name,
        'date_deb': (dateDebut ?? existingOperation.dateDebut).toIso8601String().split('T')[0],
        'date_fin': (dateFin ?? existingOperation.dateFin).toIso8601String().split('T')[0],
        'is_active': isActive ?? existingOperation.isActive,
      };

      // Appeler l'API pour mettre à jour l'opération
      final response = await _apiService.put('/operations/$id', data: data);
      
      if (response.statusCode == 200) {
        // Mettre à jour l'opération localement
        final updatedOperation = existingOperation.copyWith(
          name: name,
          dateDebut: dateDebut,
          dateFin: dateFin,
          isActive: isActive,
          lastSyncedAt: DateTime.now(),
          isSynced: true,
        );
        
        await saveOperation(updatedOperation);
        return true;
      }
      
      return false;
    } catch (e) {
      debugPrint('Erreur lors de la mise à jour de l\'opération: $e');
      return false;
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

  // Supprimer une opération via l'API
  Future<bool> deleteOperationViaApi(int id) async {
    _isLoading = true;
    notifyListeners();

    try {
      // Appeler l'API pour supprimer l'opération
      final response = await _apiService.delete('/operations/$id');
      
      if (response.statusCode == 200 || response.statusCode == 204) {
        // Supprimer l'opération localement
        await deleteOperation(id);
        return true;
      }
      
      return false;
    } catch (e) {
      debugPrint('Erreur lors de la suppression de l\'opération: $e');
      return false;
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }
}
