import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
import 'package:geosector_app/app.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:geosector_app/core/data/models/user_model.dart';
import 'package:geosector_app/core/data/models/amicale_model.dart';
import 'package:geosector_app/core/data/models/client_model.dart';
import 'package:geosector_app/core/data/models/operation_model.dart';
import 'package:geosector_app/core/data/models/sector_model.dart';
import 'package:geosector_app/core/data/models/passage_model.dart';
import 'package:geosector_app/core/data/models/membre_model.dart';
import 'package:geosector_app/core/data/models/user_sector_model.dart';
import 'package:geosector_app/core/data/models/region_model.dart';
import 'package:geosector_app/core/constants/app_keys.dart';
import 'package:geosector_app/core/services/hive_reset_service.dart';
import 'package:geosector_app/core/services/hive_reset_state_service.dart';
// Import centralisé pour les modèles chat
import 'package:geosector_app/chat/models/chat_adapters.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Configurer le routage par chemin (URLs sans #)
  setUrlStrategy(PathUrlStrategy());

  // Initialiser Hive avec gestion des erreurs
  bool hiveInitialized = false;

  try {
    // Initialiser Hive
    await Hive.initFlutter();

    // Enregistrer les adaptateurs Hive pour les modèles principaux
    Hive.registerAdapter(UserModelAdapter());
    Hive.registerAdapter(AmicaleModelAdapter());
    Hive.registerAdapter(ClientModelAdapter());
    Hive.registerAdapter(OperationModelAdapter());
    Hive.registerAdapter(SectorModelAdapter());
    Hive.registerAdapter(PassageModelAdapter());
    Hive.registerAdapter(MembreModelAdapter());
    Hive.registerAdapter(UserSectorModelAdapter());
    // TODO: Décommenter après avoir généré le fichier region_model.g.dart
    // Hive.registerAdapter(RegionModelAdapter());

    // Enregistrer les adaptateurs Hive pour le chat
    Hive.registerAdapter(ConversationModelAdapter());
    Hive.registerAdapter(MessageModelAdapter());
    Hive.registerAdapter(ParticipantModelAdapter());
    Hive.registerAdapter(AnonymousUserModelAdapter());
    Hive.registerAdapter(AudienceTargetModelAdapter());
    Hive.registerAdapter(NotificationSettingsAdapter());

    // Ouvrir uniquement les boîtes essentielles au démarrage
    try {
      // La boîte des utilisateurs est nécessaire pour vérifier si un utilisateur est déjà connecté
      await Hive.openBox<UserModel>(AppKeys.usersBoxName);
      // Boîte pour les amicales
      await Hive.openBox<AmicaleModel>(AppKeys.amicaleBoxName);
      // Boîte pour les clients
      await Hive.openBox<ClientModel>(AppKeys.clientsBoxName);
      // Boîte pour les préférences utilisateur générales
      await Hive.openBox(AppKeys.settingsBoxName);

      // Ouvrir les boîtes de chat également au démarrage pour le cache local
      await Hive.openBox<ConversationModel>(AppKeys.chatConversationsBoxName);
      await Hive.openBox<MessageModel>(AppKeys.chatMessagesBoxName);

      hiveInitialized = true;
    } catch (e) {
      debugPrint('Erreur lors de l\'ouverture des boîtes Hive: $e');
      // Une erreur s'est produite lors de l'ouverture des boîtes, probablement due à une incompatibilité
      // Nous allons réinitialiser Hive
      hiveInitialized = false;
    }
  } catch (e) {
    debugPrint('Erreur lors de l\'initialisation de Hive: $e');
    hiveInitialized = false;
  }

  // Si Hive n'a pas été initialisé correctement, marquer l'état pour afficher le dialogue
  if (!hiveInitialized) {
    debugPrint(
        'Incompatibilité détectée dans les données Hive. Marquage pour affichage du dialogue...');
    // Marquer Hive comme ayant été réinitialisé pour afficher le dialogue plus tard
    hiveResetStateService.markAsReset();
  }

  // Les autres boîtes (operations, sectors, passages, user_sector) seront ouvertes après connexion
  // dans UserRepository.login() via la méthode _ensureBoxIsOpen()

  // Définir l'orientation de l'application
  await SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
  ]);

  // Lancer l'application directement sans AppProviders
  runApp(const GeoSectorApp());
}
