import 'package:flutter/foundation.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:geosector_app/core/constants/app_keys.dart';
import 'package:geosector_app/core/data/models/user_model.dart';
import 'package:geosector_app/core/services/current_amicale_service.dart';

class CurrentUserService extends ChangeNotifier {
  static CurrentUserService? _instance;
  static CurrentUserService get instance => _instance ??= CurrentUserService._internal();

  CurrentUserService._internal();

  UserModel? _currentUser;

  /// Mode d'affichage : 'admin' ou 'user'
  /// Un admin (fkRole>=2) peut choisir de se connecter en mode 'user'
  String _displayMode = 'user';

  // === GETTERS ===
  UserModel? get currentUser => _currentUser;
  bool get isLoggedIn => _currentUser?.hasValidSession ?? false;
  int get userRole => _currentUser?.role ?? 0;
  int? get userId => _currentUser?.id;
  int? get opeUserId => _currentUser?.opeUserId; // ID dans ope_users pour l'opération active
  String? get userEmail => _currentUser?.email;
  String? get userName => _currentUser?.name;
  String? get userFirstName => _currentUser?.firstName;
  String? get sessionId => _currentUser?.sessionId;
  int? get fkEntite => _currentUser?.fkEntite;
  String? get userPhone => _currentUser?.phone;
  String? get userMobile => _currentUser?.mobile;

  /// Mode d'affichage actuel
  String get displayMode => _displayMode;

  // Vérifications de rôles (basées sur le rôle RÉEL)
  bool get isUser => userRole == 1;
  bool get isAdminAmicale => userRole == 2;
  bool get isSuperAdmin => userRole >= 3;
  bool get canAccessAdmin => isAdminAmicale || isSuperAdmin;

  /// Est-ce que l'utilisateur doit voir l'interface admin ?
  /// Prend en compte le mode d'affichage choisi à la connexion
  bool get shouldShowAdminUI {
    // Si mode user, toujours afficher UI user
    if (_displayMode == 'user') return false;

    // Si mode admin, vérifier le rôle réel
    return canAccessAdmin;
  }

  // === SETTERS ===
  Future<void> setUser(UserModel? user) async {
    _currentUser = user;
    await _saveToHive();
    notifyListeners();

    debugPrint('👤 Utilisateur défini: ${user?.email ?? 'null'}');

    // Auto-synchroniser l'amicale si l'utilisateur a une entité
    if (user?.fkEntite != null) {
      await CurrentAmicaleService.instance.loadUserAmicale();
    } else {
      await CurrentAmicaleService.instance.clearAmicale();
    }
  }

  Future<void> updateUser(UserModel updatedUser) async {
    _currentUser = updatedUser;
    await _saveToHive();
    notifyListeners();
    debugPrint('👤 Utilisateur mis à jour: ${updatedUser.email}');
  }

  Future<void> clearUser() async {
    final userEmail = _currentUser?.email;
    _currentUser = null;
    await _clearFromHive();
    await _clearDisplayMode(); // Effacer aussi le mode d'affichage
    notifyListeners();
    debugPrint('👤 Utilisateur effacé: $userEmail');
  }

  /// Définir le mode d'affichage (à appeler lors de la connexion)
  /// @param mode 'admin' ou 'user'
  Future<void> setDisplayMode(String mode) async {
    if (mode != 'admin' && mode != 'user') {
      debugPrint('⚠️ Mode d\'affichage invalide: $mode (attendu: admin ou user)');
      return;
    }

    _displayMode = mode;
    await _saveDisplayMode();
    notifyListeners();
    debugPrint('🎨 Mode d\'affichage défini: $_displayMode');
  }

  // === PERSISTENCE HIVE (nouvelle Box user) ===
  Future<void> _saveToHive() async {
    try {
      if (_currentUser != null) {
        // Sauvegarder l'utilisateur dans sa box
        final box = Hive.box<UserModel>(AppKeys.userBoxName);
        await box.put(_currentUser!.id, _currentUser!);

        // Sauvegarder l'ID dans settings pour la restauration de session
        if (Hive.isBoxOpen(AppKeys.settingsBoxName)) {
          final settingsBox = Hive.box(AppKeys.settingsBoxName);
          await settingsBox.put('current_user_id', _currentUser!.id);
          debugPrint('💾 ID utilisateur ${_currentUser!.id} sauvegardé dans settings');
        }

        debugPrint('💾 Utilisateur sauvegardé dans Box user');
      }
    } catch (e) {
      debugPrint('❌ Erreur sauvegarde utilisateur Hive: $e');
    }
  }

  Future<void> _clearFromHive() async {
    try {
      // Effacer l'utilisateur de la box
      if (_currentUser != null) {
        final box = Hive.box<UserModel>(AppKeys.userBoxName);
        await box.delete(_currentUser!.id);
      }

      // Effacer l'ID des settings
      if (Hive.isBoxOpen(AppKeys.settingsBoxName)) {
        final settingsBox = Hive.box(AppKeys.settingsBoxName);
        await settingsBox.delete('current_user_id');
        debugPrint('🗑️ ID utilisateur effacé des settings');
      }

      debugPrint('🗑️ Utilisateur effacé de Hive');
    } catch (e) {
      debugPrint('❌ Erreur effacement utilisateur Hive: $e');
    }
  }

  Future<void> loadFromHive() async {
    try {
      // 1. Récupérer l'ID utilisateur depuis settings
      if (!Hive.isBoxOpen(AppKeys.settingsBoxName)) {
        debugPrint('⚠️ Box settings non ouverte, impossible de charger l\'utilisateur');
        _currentUser = null;
        notifyListeners();
        return;
      }

      final settingsBox = Hive.box(AppKeys.settingsBoxName);
      final userId = settingsBox.get('current_user_id');

      if (userId == null) {
        debugPrint('ℹ️ Aucun current_user_id trouvé dans settings');
        _currentUser = null;
        notifyListeners();
        return;
      }

      debugPrint('🔍 Recherche utilisateur avec ID: $userId');

      // 2. Récupérer l'utilisateur avec le bon ID
      final box = Hive.box<UserModel>(AppKeys.userBoxName);
      final user = box.get(userId);

      if (user?.hasValidSession == true) {
        _currentUser = user;
        debugPrint('📥 Utilisateur chargé depuis Hive: ${user?.email} (ID: $userId)');

        // Charger le mode d'affichage sauvegardé lors de la connexion
        await _loadDisplayMode();
      } else {
        _currentUser = null;
        if (user == null) {
          debugPrint('ℹ️ Utilisateur ID $userId non trouvé dans la box');
        } else {
          debugPrint('ℹ️ Session expirée pour l\'utilisateur ${user.email}');
        }
      }

      notifyListeners();
    } catch (e) {
      debugPrint('❌ Erreur chargement utilisateur depuis Hive: $e');
      _currentUser = null;
    }
  }

  // === PERSISTENCE DU MODE D'AFFICHAGE ===
  Future<void> _saveDisplayMode() async {
    try {
      if (Hive.isBoxOpen(AppKeys.settingsBoxName)) {
        final settingsBox = Hive.box(AppKeys.settingsBoxName);
        await settingsBox.put('display_mode', _displayMode);
        debugPrint('💾 Mode d\'affichage sauvegardé: $_displayMode');
      }
    } catch (e) {
      debugPrint('❌ Erreur sauvegarde mode d\'affichage: $e');
    }
  }

  Future<void> _loadDisplayMode() async {
    try {
      if (Hive.isBoxOpen(AppKeys.settingsBoxName)) {
        final settingsBox = Hive.box(AppKeys.settingsBoxName);
        final savedMode = settingsBox.get('display_mode', defaultValue: 'user') as String;
        _displayMode = (savedMode == 'admin' || savedMode == 'user') ? savedMode : 'user';
        debugPrint('📥 Mode d\'affichage chargé: $_displayMode');
      }
    } catch (e) {
      debugPrint('❌ Erreur chargement mode d\'affichage: $e');
      _displayMode = 'user';
    }
  }

  Future<void> _clearDisplayMode() async {
    try {
      if (Hive.isBoxOpen(AppKeys.settingsBoxName)) {
        final settingsBox = Hive.box(AppKeys.settingsBoxName);
        await settingsBox.delete('display_mode');
        _displayMode = 'user'; // Reset au mode par défaut
        debugPrint('🗑️ Mode d\'affichage effacé');
      }
    } catch (e) {
      debugPrint('❌ Erreur effacement mode d\'affichage: $e');
    }
  }

  // === MÉTHODES UTILITAIRES ===
  Future<void> updateLastPath(String path) async {
    if (_currentUser != null) {
      await updateUser(_currentUser!.copyWith(lastPath: path));
    }
  }

  String? getLastPath() => _currentUser?.lastPath;

  String getDefaultRoute() {
    if (!isLoggedIn) return '/';
    return shouldShowAdminUI ? '/admin' : '/user';
  }

  String getRoleLabel() {
    switch (userRole) {
      case 1:
        return 'Utilisateur';
      case 2:
        return 'Admin Amicale';
      case 3:
        return 'Super Admin';
      default:
        return 'Inconnu';
    }
  }

  bool hasPermission(String permission) {
    switch (permission) {
      case 'admin':
        return canAccessAdmin;
      case 'super_admin':
        return isSuperAdmin;
      case 'manage_amicale':
        return canAccessAdmin;
      case 'manage_users':
        return isSuperAdmin;
      default:
        return isLoggedIn;
    }
  }

  // === RESET POUR TESTS ===
  static void reset() {
    _instance?._currentUser = null;
    _instance = null;
  }
}
