import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:geosector_app/core/constants/app_keys.dart';
import 'package:geosector_app/core/repositories/passage_repository.dart';
import 'package:geosector_app/core/repositories/user_repository.dart';

/// Service pour charger et filtrer les données de passages
class PassageDataService {
  final PassageRepository passageRepository;
  final UserRepository userRepository;

  PassageDataService({
    required this.passageRepository,
    required this.userRepository,
  });

  /// Charge les données de passage depuis Hive
  /// 
  /// [daysToShow] : Nombre de jours à afficher
  /// [excludePassageTypes] : Types de passages à exclure
  /// [userId] : ID de l'utilisateur pour filtrer les passages (null = utilisateur actuel)
  /// [showAllPassages] : Si vrai, n'applique aucun filtrage par utilisateur
  List<Map<String, dynamic>> loadPassageData({
    required int daysToShow,
    List<int> excludePassageTypes = const [2],
    int? userId,
    bool showAllPassages = false,
  }) {
    // Récupérer tous les passages
    final passages = passageRepository.getAllPassages();

    // Filtrer les passages pour exclure ceux avec fkType dans la liste d'exclusion
    final filteredPassages = passages
        .where((p) => !excludePassageTypes.contains(p.fkType))
        .toList();

    if (filteredPassages.isEmpty) {
      return [];
    }

    // Déterminer si on filtre par utilisateur ou si on prend tous les passages
    final passagesToUse = showAllPassages
        ? filteredPassages
        : _filterPassagesByUser(filteredPassages, userId);

    if (passagesToUse.isEmpty) {
      debugPrint('Aucun passage trouvé après filtrage');
      return [];
    }

    // Trouver la date du passage le plus récent (exclure ceux sans date)
    final passagesWithDate = passagesToUse.where((p) => p.passedAt != null).toList();
    if (passagesWithDate.isEmpty) {
      debugPrint('Aucun passage avec date trouvé');
      return [];
    }
    
    passagesWithDate.sort((a, b) => b.passedAt!.compareTo(a.passedAt!));
    final DateTime referenceDate = passagesWithDate.first.passedAt!;
    debugPrint(
        'Date de référence pour le graphique: ${DateFormat('dd/MM/yyyy').format(referenceDate)}');

    // Définir la date de début (N jours avant la date de référence)
    final startDate = referenceDate.subtract(Duration(days: daysToShow - 1));
    debugPrint(
        'Date de début pour le graphique: ${DateFormat('dd/MM/yyyy').format(startDate)}');
    debugPrint(
        'Plage de dates du graphique: ${DateFormat('dd/MM/yyyy').format(startDate)} - ${DateFormat('dd/MM/yyyy').format(referenceDate)}');

    // Regrouper les passages par date et type
    final Map<String, Map<int, int>> passagesByDateAndType = {};

    // Initialiser le dictionnaire avec les N derniers jours
    for (int i = daysToShow - 1; i >= 0; i--) {
      final date = referenceDate.subtract(Duration(days: i));
      final dateStr =
          '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}';
      passagesByDateAndType[dateStr] = {};
    }

    // Ajouter tous les types de passage possibles pour chaque date
    for (final dateStr in passagesByDateAndType.keys) {
      for (final typeId in AppKeys.typesPassages.keys) {
        // Exclure les types dans la liste d'exclusion
        if (!excludePassageTypes.contains(typeId)) {
          passagesByDateAndType[dateStr]![typeId] = 0;
        }
      }
    }

    // Parcourir les passages et les regrouper par date et type
    for (final passage in passagesToUse) {
      if (passage.passedAt != null &&
          passage.passedAt!
              .isAfter(startDate.subtract(const Duration(days: 1))) &&
          passage.passedAt!
              .isBefore(referenceDate.add(const Duration(days: 1)))) {
        final dateStr =
            '${passage.passedAt!.year}-${passage.passedAt!.month.toString().padLeft(2, '0')}-${passage.passedAt!.day.toString().padLeft(2, '0')}';
        final typeId = passage.fkType;

        // Vérifier que le type n'est pas exclu
        if (!excludePassageTypes.contains(typeId)) {
          // Si la date existe dans notre dictionnaire, mettre à jour le compteur
          if (passagesByDateAndType.containsKey(dateStr)) {
            if (!passagesByDateAndType[dateStr]!.containsKey(typeId)) {
              passagesByDateAndType[dateStr]![typeId] = 0;
            }
            passagesByDateAndType[dateStr]![typeId] =
                (passagesByDateAndType[dateStr]![typeId] ?? 0) + 1;
          }
        }
      }
    }

    // Convertir les données au format attendu par le graphique
    final List<Map<String, dynamic>> result = [];
    passagesByDateAndType.forEach((dateStr, typesCounts) {
      typesCounts.forEach((typeId, count) {
        result.add({
          'date': dateStr,
          'type_passage': typeId,
          'nb': count,
        });
      });
    });

    return result;
  }

  /// Filtre les passages par utilisateur
  List<dynamic> _filterPassagesByUser(List<dynamic> passages, int? userId) {
    // Récupérer l'ID de l'utilisateur actuel si nécessaire
    final int? currentUserId = userId ?? userRepository.getCurrentUser()?.id;
        
    // Filtrer les passages pour l'utilisateur actuel
    final userPassages = passages
        .where((p) => currentUserId == null || p.fkUser == currentUserId)
        .toList();
        
    if (userPassages.isEmpty) {
      debugPrint('Aucun passage trouvé pour l\'utilisateur $currentUserId');
    }
    
    return userPassages;
  }
  
  /// Charge et prépare les données pour le graphique en camembert
  /// 
  /// [excludePassageTypes] : Types de passages à exclure
  /// [userId] : ID de l'utilisateur pour filtrer les passages (null = utilisateur actuel)
  /// [showAllPassages] : Si vrai, n'applique aucun filtrage par utilisateur
  Map<int, int> loadPassageDataForPieChart({
    List<int> excludePassageTypes = const [2],
    int? userId,
    bool showAllPassages = false,
  }) {
    // Récupérer tous les passages
    final passages = passageRepository.getAllPassages();

    // Filtrer les passages pour exclure ceux avec fkType dans la liste d'exclusion
    final filteredPassages = passages
        .where((p) => !excludePassageTypes.contains(p.fkType))
        .toList();

    if (filteredPassages.isEmpty) {
      return {};
    }

    // Déterminer si on filtre par utilisateur ou si on prend tous les passages
    final passagesToUse = showAllPassages
        ? filteredPassages
        : _filterPassagesByUser(filteredPassages, userId);

    if (passagesToUse.isEmpty) {
      debugPrint('Aucun passage trouvé après filtrage');
      return {};
    }

    // Compter les passages par type
    final Map<int, int> passagesByType = {};
    
    // Initialiser les compteurs pour tous les types de passage
    for (final typeId in AppKeys.typesPassages.keys) {
      // Exclure les types dans la liste d'exclusion
      if (!excludePassageTypes.contains(typeId)) {
        passagesByType[typeId] = 0;
      }
    }
    
    // Compter les passages par type
    for (final passage in passagesToUse) {
      final typeId = passage.fkType;
      if (!excludePassageTypes.contains(typeId)) {
        passagesByType[typeId] = (passagesByType[typeId] ?? 0) + 1;
      }
    }
    
    return passagesByType;
  }
}
