import 'package:flutter/material.dart';
import 'package:geosector_app/core/constants/app_keys.dart';
import 'package:geosector_app/presentation/widgets/charts/passage_data.dart';
import 'package:intl/intl.dart';

/// Utilitaires pour les passages et règlements
class PassageUtils {
  /// Convertit les données de passage brutes en liste de PassageData
  ///
  /// [passageData] est une liste d'objets contenant date, type_passage et nb
  static List<List<PassageData>> getPassageDataByType(
      List<Map<String, dynamic>> passageData) {
    // Créer un Map pour stocker les données par type de passage
    final Map<int, List<PassageData>> passagesByType = {};

    // Initialiser les listes pour chaque type de passage
    for (final entry in AppKeys.typesPassages.entries) {
      passagesByType[entry.key] = [];
    }

    // Grouper les passages par type
    for (final data in passageData) {
      final int typeId = data['type_passage'];
      final int count = data['nb'];

      if (AppKeys.typesPassages.containsKey(typeId)) {
        final typeData = AppKeys.typesPassages[typeId]!;
        final Color color = Color(typeData['couleur1'] as int);
        final String iconPath = typeData['icone'] as String;
        final String title = typeData['titre'] as String;

        // Utiliser la méthode factory qui gère les dates au format ISO 8601
        if (data['date'] is String) {
          passagesByType[typeId]!.add(
            PassageData.fromIsoDate(
              isoDate: data['date'],
              typeId: typeId,
              count: count,
              color: color,
              iconPath: iconPath,
              title: title,
            ),
          );
        } else {
          // Fallback pour les objets DateTime (pour compatibilité)
          final DateTime date = data['date'] as DateTime;
          passagesByType[typeId]!.add(
            PassageData(
              date: date,
              typeId: typeId,
              count: count,
              color: color,
              iconPath: iconPath,
              title: title,
            ),
          );
        }
      }
    }

    // Convertir le Map en liste de listes
    return passagesByType.values.toList();
  }

  /// Convertit les données de règlement brutes en liste de PaymentAmountData
  ///
  /// [paymentData] est une liste d'objets contenant date, type_reglement et montant
  static List<List<PaymentAmountData>> getPaymentDataByType(
      List<Map<String, dynamic>> paymentData) {
    // Créer un Map pour stocker les données par type de règlement
    final Map<int, List<PaymentAmountData>> paymentsByType = {};

    // Initialiser les listes pour chaque type de règlement (sauf 0 qui est "Pas de règlement")
    for (final entry in AppKeys.typesReglements.entries) {
      if (entry.key > 0) {
        // Ignorer le type 0 (Pas de règlement)
        paymentsByType[entry.key] = [];
      }
    }

    // Grouper les règlements par type
    for (final data in paymentData) {
      final int typeId = data['type_reglement'];
      final double amount = data['montant'] is double
          ? data['montant']
          : double.parse(data['montant'].toString());

      if (typeId > 0 && AppKeys.typesReglements.containsKey(typeId)) {
        final typeData = AppKeys.typesReglements[typeId]!;
        final Color color = Color(typeData['couleur'] as int);
        final dynamic iconData = _getIconForPaymentType(typeId);
        final String title = typeData['titre'] as String;

        // Utiliser la méthode factory qui gère les dates au format ISO 8601
        if (data['date'] is String) {
          paymentsByType[typeId]!.add(
            PaymentAmountData.fromIsoDate(
              isoDate: data['date'],
              typeId: typeId,
              amount: amount,
              color: color,
              iconData: iconData,
              title: title,
            ),
          );
        } else {
          // Fallback pour les objets DateTime (pour compatibilité)
          final DateTime date = data['date'] as DateTime;
          paymentsByType[typeId]!.add(
            PaymentAmountData(
              date: date,
              typeId: typeId,
              amount: amount,
              color: color,
              iconData: iconData,
              title: title,
            ),
          );
        }
      }
    }

    // Convertir le Map en liste de listes
    return paymentsByType.values.toList();
  }

  /// Génère des données de passage fictives pour les 14 derniers jours
  static List<Map<String, dynamic>> generateMockPassageData() {
    final List<Map<String, dynamic>> mockData = [];
    final now = DateTime.now();

    for (int i = 13; i >= 0; i--) {
      final date = now.subtract(Duration(days: i));

      // Ajouter des données pour chaque type de passage
      for (int typeId = 1; typeId <= 6; typeId++) {
        // Générer un nombre aléatoire de passages entre 0 et 5
        final count = (typeId == 1 || typeId == 2)
            ? (1 + (date.day % 5)) // Plus de passages pour les types 1 et 2
            : (date.day % 3); // Moins pour les autres types

        if (count > 0) {
          mockData.add({
            'date': date,
            'type_passage': typeId,
            'nb': count,
          });
        }
      }
    }

    return mockData;
  }

  /// Génère des données de règlement fictives pour les 14 derniers jours
  static List<Map<String, dynamic>> generateMockPaymentData() {
    final List<Map<String, dynamic>> mockData = [];
    final now = DateTime.now();

    for (int i = 13; i >= 0; i--) {
      final date = now.subtract(Duration(days: i));

      // Ajouter des données pour chaque type de règlement
      for (int typeId = 1; typeId <= 3; typeId++) {
        // Générer un montant aléatoire
        final amount = (typeId * 100.0) + (date.day * 10.0);

        mockData.add({
          'date': date,
          'type_reglement': typeId,
          'montant': amount,
        });
      }
    }

    return mockData;
  }

  /// Obtenir l'icône correspondant au type de règlement
  /// Retourne un IconData pour les règlements car ils n'ont pas de chemin d'icône défini dans AppKeys
  static IconData _getIconForPaymentType(int typeId) {
    switch (typeId) {
      case 1: // Espèces
        return Icons.payments;
      case 2: // Chèque
        return Icons.money;
      case 3: // CB
        return Icons.credit_card;
      default:
        return Icons.euro;
    }
  }

  /// Formater une date pour l'affichage dans les graphiques
  static String formatDateForChart(DateTime date, String periodType) {
    switch (periodType.toLowerCase()) {
      case 'jour':
        return DateFormat('dd/MM').format(date);
      case 'semaine':
        // Calculer le numéro de la semaine dans l'année
        final firstDayOfYear = DateTime(date.year, 1, 1);
        final dayOfYear = date.difference(firstDayOfYear).inDays;
        final weekNumber =
            ((dayOfYear + firstDayOfYear.weekday - 1) / 7).ceil();
        return 'S$weekNumber';
      case 'mois':
        return DateFormat('MMM').format(date);
      case 'année':
        return DateFormat('yyyy').format(date);
      default:
        return DateFormat('dd/MM').format(date);
    }
  }
}
