import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart' show kIsWeb;

/// Service qui gère la surveillance de l'état de connectivité de l'appareil
class ConnectivityService extends ChangeNotifier {
  final Connectivity _connectivity = Connectivity();
  late StreamSubscription<List<ConnectivityResult>> _connectivitySubscription;
  
  List<ConnectivityResult> _connectionStatus = [ConnectivityResult.none];
  bool _isInitialized = false;

  /// Indique si l'appareil est connecté à Internet
  bool get isConnected {
    // Vérifie si la liste contient au moins un type de connexion autre que 'none'
    return _connectionStatus.any((result) => result != ConnectivityResult.none);
  }
  
  /// Indique si l'appareil est connecté via WiFi
  bool get isWifi => _connectionStatus.contains(ConnectivityResult.wifi);
  
  /// Indique si l'appareil est connecté via données mobiles (4G, 5G, etc.)
  bool get isMobile => _connectionStatus.contains(ConnectivityResult.mobile);
  
  /// Retourne le type de connexion actuel (WiFi, données mobiles, etc.)
  List<ConnectivityResult> get connectionStatus => _connectionStatus;
  
  /// Retourne le premier type de connexion actif (pour compatibilité avec l'ancien code)
  ConnectivityResult get primaryConnectionStatus {
    // Retourne le premier type de connexion qui n'est pas 'none', ou 'none' si tous sont 'none'
    return _connectionStatus.firstWhere(
      (result) => result != ConnectivityResult.none,
      orElse: () => ConnectivityResult.none
    );
  }
  
  /// Obtient une description textuelle du type de connexion
  String get connectionType {
    // Si aucune connexion n'est disponible
    if (!isConnected) {
      return 'Aucune connexion';
    }
    
    // Utiliser le premier type de connexion actif
    ConnectivityResult primaryStatus = primaryConnectionStatus;
    
    switch (primaryStatus) {
      case ConnectivityResult.wifi:
        return 'WiFi';
      case ConnectivityResult.mobile:
        return 'Données mobiles';
      case ConnectivityResult.ethernet:
        return 'Ethernet';
      case ConnectivityResult.bluetooth:
        return 'Bluetooth';
      case ConnectivityResult.vpn:
        return 'VPN';
      case ConnectivityResult.none:
        return 'Aucune connexion';
      default:
        return 'Inconnu';
    }
  }

  /// Constructeur du service de connectivité
  ConnectivityService() {
    // Initialiser avec une connexion par défaut (supposée disponible)
    // Ceci sera mis à jour rapidement par _initConnectivity()
    if (kIsWeb) {
      _connectionStatus = [ConnectivityResult.wifi];
    } else {
      // Sur mobile, on suppose qu'il y a au moins une connexion jusqu'à vérification
      _connectionStatus = [ConnectivityResult.wifi];
    }
    _initConnectivity();
  }

  /// Initialise le service et commence à écouter les changements de connectivité
  Future<void> _initConnectivity() async {
    if (_isInitialized) return;
    
    try {
      // En version web, on considère par défaut que la connexion est disponible
      // car la vérification de connectivité est moins fiable sur le web
      if (kIsWeb) {
        _connectionStatus = [ConnectivityResult.wifi]; // Valeur par défaut pour le web
      } else {
        final result = await _connectivity.checkConnectivity();
        _connectionStatus = result;
      }
      
      // S'abonner aux changements de connectivité
      _connectivitySubscription = _connectivity.onConnectivityChanged.listen((List<ConnectivityResult> results) {
        _updateConnectionStatus(results);
      });
      _isInitialized = true;
    } catch (e) {
      debugPrint('Erreur lors de l\'initialisation du service de connectivité: $e');
      
      // En cas d'erreur en version web, on suppose que la connexion est disponible
      // car l'application web ne peut pas fonctionner sans connexion de toute façon
      if (kIsWeb) {
        _connectionStatus = [ConnectivityResult.wifi];
        _isInitialized = true;
      }
    }
    
    notifyListeners();
  }

  /// Met à jour l'état de la connexion lorsqu'il change
  void _updateConnectionStatus(List<ConnectivityResult> results) {
    // Vérifier si la liste des résultats a changé
    bool hasChanged = false;
    
    // Si les listes ont des longueurs différentes, elles sont différentes
    if (_connectionStatus.length != results.length) {
      hasChanged = true;
    } else {
      // Vérifier si les éléments sont différents
      for (int i = 0; i < _connectionStatus.length; i++) {
        if (i >= results.length || _connectionStatus[i] != results[i]) {
          hasChanged = true;
          break;
        }
      }
    }
    
    if (hasChanged) {
      _connectionStatus = results;
      notifyListeners();
    }
  }

  /// Vérifie manuellement l'état actuel de la connexion
  Future<List<ConnectivityResult>> checkConnectivity() async {
    try {
      // En version web, on considère par défaut que la connexion est disponible
      if (kIsWeb) {
        // En version web, on peut tenter de faire une requête réseau légère pour vérifier la connectivité
        // mais pour l'instant, on suppose que la connexion est disponible
        final results = [ConnectivityResult.wifi];
        _updateConnectionStatus(results);
        return results;
      } else {
        // Version mobile - utiliser l'API standard
        final result = await _connectivity.checkConnectivity();
        _updateConnectionStatus(result);
        return result;
      }
    } catch (e) {
      debugPrint('Erreur lors de la vérification de la connectivité: $e');
      // En cas d'erreur, on conserve l'état actuel
      return _connectionStatus;
    }
  }

  @override
  void dispose() {
    try {
      _connectivitySubscription.cancel();
    } catch (e) {
      debugPrint('Erreur lors de l\'annulation de l\'abonnement de connectivité: $e');
    }
    super.dispose();
  }
}
