import 'package:flutter/foundation.dart';
import 'package:geosector_app/core/services/api_service.dart';
import 'package:geosector_app/core/data/models/event_stats_model.dart';
import 'package:geosector_app/core/utils/api_exception.dart';
import 'package:intl/intl.dart';

/// Service pour récupérer les statistiques d'événements depuis l'API.
///
/// Ce service est un singleton qui gère les appels API vers les endpoints
/// /api/events/stats/*. Il est accessible uniquement aux admins (rôle >= 2).
class EventStatsService {
  static EventStatsService? _instance;

  EventStatsService._internal();

  static EventStatsService get instance {
    _instance ??= EventStatsService._internal();
    return _instance!;
  }

  final _dateFormat = DateFormat('yyyy-MM-dd');

  /// Récupère le résumé des stats pour une date donnée.
  ///
  /// GET /api/events/stats/summary?date=YYYY-MM-DD&entity_id=X
  ///
  /// [date] : Date à récupérer (défaut: aujourd'hui)
  /// [entityId] : ID de l'entité (super-admin uniquement, optionnel)
  Future<EventSummary> getSummary({
    DateTime? date,
    int? entityId,
  }) async {
    try {
      final queryParams = <String, dynamic>{};

      if (date != null) {
        queryParams['date'] = _dateFormat.format(date);
      }

      if (entityId != null) {
        queryParams['entity_id'] = entityId.toString();
      }

      debugPrint('📊 [EventStats] Récupération résumé: $queryParams');

      final response = await ApiService.instance.get(
        '/events/stats/summary',
        queryParameters: queryParams.isNotEmpty ? queryParams : null,
      );

      if (response.data['status'] == 'success') {
        return EventSummary.fromJson(response.data['data']);
      } else {
        throw ApiException(
          response.data['message'] ?? 'Erreur lors de la récupération du résumé',
        );
      }
    } catch (e) {
      debugPrint('❌ [EventStats] Erreur getSummary: $e');
      if (e is ApiException) rethrow;
      throw ApiException('Erreur lors de la récupération des statistiques', originalError: e);
    }
  }

  /// Récupère les stats quotidiennes pour une période.
  ///
  /// GET /api/events/stats/daily?from=YYYY-MM-DD&to=YYYY-MM-DD&events=type1,type2
  ///
  /// [from] : Date de début (obligatoire)
  /// [to] : Date de fin (obligatoire)
  /// [events] : Types d'événements à filtrer (optionnel)
  /// [entityId] : ID de l'entité (super-admin uniquement, optionnel)
  ///
  /// Limite : 90 jours maximum
  Future<DailyStats> getDailyStats({
    required DateTime from,
    required DateTime to,
    List<String>? events,
    int? entityId,
  }) async {
    try {
      // Vérifier la limite de 90 jours
      final daysDiff = to.difference(from).inDays;
      if (daysDiff > 90) {
        throw const ApiException('La période ne peut pas dépasser 90 jours');
      }

      final queryParams = <String, dynamic>{
        'from': _dateFormat.format(from),
        'to': _dateFormat.format(to),
      };

      if (events != null && events.isNotEmpty) {
        queryParams['events'] = events.join(',');
      }

      if (entityId != null) {
        queryParams['entity_id'] = entityId.toString();
      }

      debugPrint('📊 [EventStats] Récupération stats quotidiennes: $queryParams');

      final response = await ApiService.instance.get(
        '/events/stats/daily',
        queryParameters: queryParams,
      );

      if (response.data['status'] == 'success') {
        return DailyStats.fromJson(response.data['data']);
      } else {
        throw ApiException(
          response.data['message'] ?? 'Erreur lors de la récupération des stats quotidiennes',
        );
      }
    } catch (e) {
      debugPrint('❌ [EventStats] Erreur getDailyStats: $e');
      if (e is ApiException) rethrow;
      throw ApiException('Erreur lors de la récupération des statistiques quotidiennes', originalError: e);
    }
  }

  /// Récupère les stats hebdomadaires pour une période.
  ///
  /// GET /api/events/stats/weekly?from=YYYY-MM-DD&to=YYYY-MM-DD&events=type1,type2
  ///
  /// [from] : Date de début (obligatoire)
  /// [to] : Date de fin (obligatoire)
  /// [events] : Types d'événements à filtrer (optionnel)
  /// [entityId] : ID de l'entité (super-admin uniquement, optionnel)
  ///
  /// Limite : 365 jours maximum
  Future<WeeklyStats> getWeeklyStats({
    required DateTime from,
    required DateTime to,
    List<String>? events,
    int? entityId,
  }) async {
    try {
      // Vérifier la limite de 365 jours
      final daysDiff = to.difference(from).inDays;
      if (daysDiff > 365) {
        throw const ApiException('La période ne peut pas dépasser 365 jours');
      }

      final queryParams = <String, dynamic>{
        'from': _dateFormat.format(from),
        'to': _dateFormat.format(to),
      };

      if (events != null && events.isNotEmpty) {
        queryParams['events'] = events.join(',');
      }

      if (entityId != null) {
        queryParams['entity_id'] = entityId.toString();
      }

      debugPrint('📊 [EventStats] Récupération stats hebdomadaires: $queryParams');

      final response = await ApiService.instance.get(
        '/events/stats/weekly',
        queryParameters: queryParams,
      );

      if (response.data['status'] == 'success') {
        return WeeklyStats.fromJson(response.data['data']);
      } else {
        throw ApiException(
          response.data['message'] ?? 'Erreur lors de la récupération des stats hebdomadaires',
        );
      }
    } catch (e) {
      debugPrint('❌ [EventStats] Erreur getWeeklyStats: $e');
      if (e is ApiException) rethrow;
      throw ApiException('Erreur lors de la récupération des statistiques hebdomadaires', originalError: e);
    }
  }

  /// Récupère les stats mensuelles pour une année.
  ///
  /// GET /api/events/stats/monthly?year=YYYY&events=type1,type2
  ///
  /// [year] : Année (défaut: année courante)
  /// [events] : Types d'événements à filtrer (optionnel)
  /// [entityId] : ID de l'entité (super-admin uniquement, optionnel)
  Future<MonthlyStats> getMonthlyStats({
    int? year,
    List<String>? events,
    int? entityId,
  }) async {
    try {
      final queryParams = <String, dynamic>{};

      if (year != null) {
        queryParams['year'] = year.toString();
      }

      if (events != null && events.isNotEmpty) {
        queryParams['events'] = events.join(',');
      }

      if (entityId != null) {
        queryParams['entity_id'] = entityId.toString();
      }

      debugPrint('📊 [EventStats] Récupération stats mensuelles: $queryParams');

      final response = await ApiService.instance.get(
        '/events/stats/monthly',
        queryParameters: queryParams.isNotEmpty ? queryParams : null,
      );

      if (response.data['status'] == 'success') {
        return MonthlyStats.fromJson(response.data['data']);
      } else {
        throw ApiException(
          response.data['message'] ?? 'Erreur lors de la récupération des stats mensuelles',
        );
      }
    } catch (e) {
      debugPrint('❌ [EventStats] Erreur getMonthlyStats: $e');
      if (e is ApiException) rethrow;
      throw ApiException('Erreur lors de la récupération des statistiques mensuelles', originalError: e);
    }
  }

  /// Récupère les détails des événements pour une date.
  ///
  /// GET /api/events/stats/details?date=YYYY-MM-DD&event=type&limit=50&offset=0
  ///
  /// [date] : Date à récupérer (obligatoire)
  /// [event] : Type d'événement à filtrer (optionnel)
  /// [limit] : Nombre de résultats max (défaut: 50, max: 100)
  /// [offset] : Pagination (défaut: 0)
  /// [entityId] : ID de l'entité (super-admin uniquement, optionnel)
  Future<EventDetails> getDetails({
    required DateTime date,
    String? event,
    int? limit,
    int? offset,
    int? entityId,
  }) async {
    try {
      final queryParams = <String, dynamic>{
        'date': _dateFormat.format(date),
      };

      if (event != null && event.isNotEmpty) {
        queryParams['event'] = event;
      }

      if (limit != null) {
        queryParams['limit'] = limit.toString();
      }

      if (offset != null) {
        queryParams['offset'] = offset.toString();
      }

      if (entityId != null) {
        queryParams['entity_id'] = entityId.toString();
      }

      debugPrint('📊 [EventStats] Récupération détails: $queryParams');

      final response = await ApiService.instance.get(
        '/events/stats/details',
        queryParameters: queryParams,
      );

      if (response.data['status'] == 'success') {
        return EventDetails.fromJson(response.data['data']);
      } else {
        throw ApiException(
          response.data['message'] ?? 'Erreur lors de la récupération des détails',
        );
      }
    } catch (e) {
      debugPrint('❌ [EventStats] Erreur getDetails: $e');
      if (e is ApiException) rethrow;
      throw ApiException('Erreur lors de la récupération des détails', originalError: e);
    }
  }

  /// Récupère les types d'événements disponibles.
  ///
  /// GET /api/events/stats/types
  Future<EventTypes> getEventTypes() async {
    try {
      debugPrint('📊 [EventStats] Récupération types d\'événements');

      final response = await ApiService.instance.get('/events/stats/types');

      if (response.data['status'] == 'success') {
        return EventTypes.fromJson(response.data['data']);
      } else {
        throw ApiException(
          response.data['message'] ?? 'Erreur lors de la récupération des types',
        );
      }
    } catch (e) {
      debugPrint('❌ [EventStats] Erreur getEventTypes: $e');
      if (e is ApiException) rethrow;
      throw ApiException('Erreur lors de la récupération des types d\'événements', originalError: e);
    }
  }

  /// Réinitialise le singleton (pour les tests)
  static void reset() {
    _instance = null;
  }
}
