import 'package:dio/dio.dart';
import 'package:injectable/injectable.dart';
import 'package:unionflow_mobile_apps/core/network/api_client.dart';
import 'package:unionflow_mobile_apps/core/utils/logger.dart';

import '../../../../shared/models/membre_search_criteria.dart';
import '../../../../shared/models/membre_search_result.dart';

/// Service pour la recherche avancée de membres
/// Gère les appels API vers l'endpoint de recherche sophistiquée
@lazySingleton
class MembreSearchService {
  final ApiClient _apiClient;

  MembreSearchService(this._apiClient);

  /// Effectue une recherche avancée de membres
  ///
  /// [criteria] Critères de recherche
  /// [page] Numéro de page (0-based)
  /// [size] Taille de la page
  /// [sortField] Champ de tri
  /// [sortDirection] Direction du tri (asc/desc)
  ///
  /// Returns [MembreSearchResult] avec les résultats paginés
  Future<MembreSearchResult> searchMembresAdvanced({
    required MembreSearchCriteria criteria,
    int page = 0,
    int size = 20,
    String sortField = 'nom',
    String sortDirection = 'asc',
  }) async {
    AppLogger.info('Recherche avancée de membres: ${criteria.description}');

    try {
      // Validation des critères
      if (!criteria.hasAnyCriteria) {
        throw Exception('Au moins un critère de recherche doit être spécifié');
      }

      if (!criteria.isValid) {
        throw Exception('Critères de recherche invalides');
      }

      // Préparation des paramètres de requête
      final queryParams = {
        'page': page.toString(),
        'size': size.toString(),
        'sort': sortField,
        'direction': sortDirection,
      };

      // Appel API
      final response = await _apiClient.post(
        '/api/membres/search/advanced',
        data: criteria.toJson(),
        queryParameters: queryParams,
      );

      // Parsing de la réponse
      final result = MembreSearchResult.fromJson(response.data);

      AppLogger.info('Recherche terminée: ${result.totalElements} résultats en ${result.executionTimeMs}ms');

      return result;
    } on DioException catch (e, st) {
      AppLogger.error('MembreSearchService: recherche avancée échouée', error: e, stackTrace: st);
      rethrow;
    } catch (e, st) {
      AppLogger.error('MembreSearchService: erreur inattendue recherche', error: e, stackTrace: st);
      rethrow;
    }
  }

  /// Recherche rapide par terme général
  /// 
  /// [query] Terme de recherche
  /// [page] Numéro de page
  /// [size] Taille de la page
  /// 
  /// Returns [MembreSearchResult] avec les résultats
  Future<MembreSearchResult> quickSearch({
    required String query,
    int page = 0,
    int size = 20,
  }) async {
    final criteria = MembreSearchCriteria.quickSearch(query);
    return searchMembresAdvanced(
      criteria: criteria,
      page: page,
      size: size,
    );
  }

  /// Recherche des membres actifs uniquement
  /// 
  /// [page] Numéro de page
  /// [size] Taille de la page
  /// 
  /// Returns [MembreSearchResult] avec les membres actifs
  Future<MembreSearchResult> searchActiveMembers({
    int page = 0,
    int size = 20,
  }) async {
    return searchMembresAdvanced(
      criteria: MembreSearchCriteria.activeMembers,
      page: page,
      size: size,
    );
  }

  /// Recherche des membres du bureau
  /// 
  /// [page] Numéro de page
  /// [size] Taille de la page
  /// 
  /// Returns [MembreSearchResult] avec les membres du bureau
  Future<MembreSearchResult> searchBureauMembers({
    int page = 0,
    int size = 20,
  }) async {
    return searchMembresAdvanced(
      criteria: MembreSearchCriteria.bureauMembers,
      page: page,
      size: size,
    );
  }

  /// Recherche par organisation
  /// 
  /// [organisationIds] Liste des IDs d'organisations
  /// [page] Numéro de page
  /// [size] Taille de la page
  /// 
  /// Returns [MembreSearchResult] avec les membres des organisations
  Future<MembreSearchResult> searchByOrganisations({
    required List<String> organisationIds,
    int page = 0,
    int size = 20,
  }) async {
    final criteria = MembreSearchCriteria(
      organisationIds: organisationIds,
      statut: 'ACTIF',
    );
    return searchMembresAdvanced(
      criteria: criteria,
      page: page,
      size: size,
    );
  }

  /// Recherche par tranche d'âge
  /// 
  /// [ageMin] Âge minimum
  /// [ageMax] Âge maximum
  /// [page] Numéro de page
  /// [size] Taille de la page
  /// 
  /// Returns [MembreSearchResult] avec les membres dans la tranche d'âge
  Future<MembreSearchResult> searchByAgeRange({
    int? ageMin,
    int? ageMax,
    int page = 0,
    int size = 20,
  }) async {
    final criteria = MembreSearchCriteria(
      ageMin: ageMin,
      ageMax: ageMax,
      statut: 'ACTIF',
    );
    return searchMembresAdvanced(
      criteria: criteria,
      page: page,
      size: size,
    );
  }

  /// Recherche par région
  /// 
  /// [region] Nom de la région
  /// [page] Numéro de page
  /// [size] Taille de la page
  /// 
  /// Returns [MembreSearchResult] avec les membres de la région
  Future<MembreSearchResult> searchByRegion({
    required String region,
    int page = 0,
    int size = 20,
  }) async {
    final criteria = MembreSearchCriteria(
      region: region,
      statut: 'ACTIF',
    );
    return searchMembresAdvanced(
      criteria: criteria,
      page: page,
      size: size,
    );
  }

  /// Recherche par rôles
  /// 
  /// [roles] Liste des rôles
  /// [page] Numéro de page
  /// [size] Taille de la page
  /// 
  /// Returns [MembreSearchResult] avec les membres ayant ces rôles
  Future<MembreSearchResult> searchByRoles({
    required List<String> roles,
    int page = 0,
    int size = 20,
  }) async {
    final criteria = MembreSearchCriteria(
      roles: roles,
      statut: 'ACTIF',
    );
    return searchMembresAdvanced(
      criteria: criteria,
      page: page,
      size: size,
    );
  }

  /// Recherche par période d'adhésion
  /// 
  /// [dateMin] Date minimum (ISO 8601)
  /// [dateMax] Date maximum (ISO 8601)
  /// [page] Numéro de page
  /// [size] Taille de la page
  /// 
  /// Returns [MembreSearchResult] avec les membres adhérés dans la période
  Future<MembreSearchResult> searchByAdhesionPeriod({
    String? dateMin,
    String? dateMax,
    int page = 0,
    int size = 20,
  }) async {
    final criteria = MembreSearchCriteria(
      dateAdhesionMin: dateMin,
      dateAdhesionMax: dateMax,
      statut: 'ACTIF',
    );
    return searchMembresAdvanced(
      criteria: criteria,
      page: page,
      size: size,
    );
  }

  /// Valide les critères de recherche avant envoi
  bool validateCriteria(MembreSearchCriteria criteria) {
    if (!criteria.hasAnyCriteria) {
      AppLogger.warning('MembreSearchService: aucun critère de recherche spécifié');
      return false;
    }

    if (!criteria.isValid) {
      AppLogger.warning('MembreSearchService: critères invalides', tag: criteria.description);
      return false;
    }

    return true;
  }

  /// Estime le temps de recherche basé sur les critères
  Duration estimateSearchTime(MembreSearchCriteria criteria) {
    // Estimation basique - peut être améliorée avec des métriques réelles
    int complexityScore = 0;

    if (criteria.query?.isNotEmpty == true) complexityScore += 2;
    if (criteria.organisationIds?.isNotEmpty == true) complexityScore += 1;
    if (criteria.roles?.isNotEmpty == true) complexityScore += 1;
    if (criteria.ageMin != null || criteria.ageMax != null) complexityScore += 1;
    if (criteria.dateAdhesionMin != null || criteria.dateAdhesionMax != null) complexityScore += 1;

    // Temps de base + complexité
    const baseTime = 100; // 100ms de base
    final additionalTime = complexityScore * 50; // 50ms par critère

    return Duration(milliseconds: baseTime + additionalTime);
  }
}
