import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:http/http.dart' as http;
import 'package:intl/date_symbol_data_local.dart';
import 'package:provider/provider.dart';

import 'config/injection/injection.dart';
import 'config/router.dart';
import 'core/constants/env_config.dart';
import 'core/theme/theme_provider.dart';
import 'core/utils/app_logger.dart';
import 'data/datasources/event_remote_data_source.dart';
import 'data/datasources/notification_remote_data_source.dart';
import 'data/providers/friends_provider.dart';
import 'data/providers/presence_provider.dart';
import 'data/providers/user_provider.dart';
import 'data/repositories/friends_repository_impl.dart';
import 'data/services/notification_service.dart';
import 'data/services/preferences_helper.dart';
import 'data/services/realtime_notification_service.dart';
import 'data/services/secure_storage.dart';
import 'domain/entities/user.dart';
import 'presentation/state_management/event_bloc.dart';
import 'presentation/widgets/realtime_notification_handler.dart';

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

  // Validation de la configuration au démarrage
  try {
    EnvConfig.validate(throwOnError: true);
    AppLogger.i('Configuration validée avec succès', tag: 'Main');
    AppLogger.d(EnvConfig.getConfigSummary(), tag: 'Main');
  } on ConfigurationException catch (e, stackTrace) {
    AppLogger.e(
      'Erreur de configuration au démarrage',
      error: e,
      stackTrace: stackTrace,
      tag: 'Main',
    );
    // En production, on ne peut pas continuer avec une configuration invalide
    if (EnvConfig.isProduction) {
      throw e;
    }
    // En développement, on continue mais on log l'erreur
    AppLogger.w('Continuité en mode développement malgré les erreurs de configuration', tag: 'Main');
  }

  // Initialisation de l'injection de dépendances
  init();

  // Initialisation du format de date en français
  await initializeDateFormatting('fr_FR');

  // Récupération des services depuis GetIt
  final secureStorage = sl<SecureStorage>();
  final preferencesHelper = sl<PreferencesHelper>();

  // Récupération des informations stockées avec logs détaillés
  String? userId = await secureStorage.getUserId();
  String? userFirstName = await preferencesHelper.getUseFirstrName();
  String? userLastName = await preferencesHelper.getUserLastName();

  // Log de la récupération des informations
  AppLogger.i(
    'Récupération des informations utilisateur : userId = $userId, userFirstName = $userFirstName, userLastName = $userLastName',
    tag: 'Main',
  );

  // Gestion des valeurs par défaut si les informations ne sont pas trouvées
  userId ??= 'default_user_id';
  userFirstName ??= 'Default';
  userLastName ??= 'User';

  // Log des valeurs par défaut appliquées
  AppLogger.i(
    'Valeurs par défaut appliquées : userId = $userId, userFirstName = $userFirstName, userLastName = $userLastName',
    tag: 'Main',
  );

  // Création de l'objet User
  final User user = User(
    userId: userId,
    userLastName: userLastName,
    userFirstName: userFirstName,
    email: 'user@example.com',
    motDePasse: 'motDePasseHashé',
    profileImageUrl: 'lib/assets/images/profile_picture.png',
  );

  runApp(MyApp(user: user));
}

class MyApp extends StatefulWidget {
  const MyApp({
    required this.user,
    super.key,
  });
  final User user;

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  RealtimeNotificationService? _realtimeService;
  bool _isInitialized = false;

  @override
  void initState() {
    super.initState();
    _initializeRealtime();
  }

  /// Initialise le service de notifications temps réel.
  Future<void> _initializeRealtime() async {
    try {
      // Vérifier si l'utilisateur est connecté (pas de valeur par défaut)
      if (widget.user.userId == 'default_user_id') {
        AppLogger.w('Utilisateur non connecté, service temps réel non initialisé', tag: 'MyApp');
        setState(() => _isInitialized = true);
        return;
      }

      AppLogger.i('Initialisation du service temps réel pour userId: ${widget.user.userId}', tag: 'MyApp');

      // Créer le service temps réel
      _realtimeService = RealtimeNotificationService(widget.user.userId);
      await _realtimeService!.connect();

      AppLogger.i('Service temps réel connecté avec succès', tag: 'MyApp');

      setState(() => _isInitialized = true);
    } catch (e, stackTrace) {
      AppLogger.e('Erreur lors de l\'initialisation du service temps réel', error: e, stackTrace: stackTrace, tag: 'MyApp');
      setState(() => _isInitialized = true);
    }
  }

  /// Connecte le service temps réel aux providers après leur création.
  void _connectProvidersToRealtime(BuildContext context) {
    if (_realtimeService == null) return;

    try {
      // Connecter FriendsProvider
      final friendsProvider = Provider.of<FriendsProvider>(context, listen: false);
      friendsProvider.connectRealtime(_realtimeService!);
      AppLogger.i('FriendsProvider connecté au service temps réel', tag: 'MyApp');

      // Connecter PresenceProvider
      final presenceProvider = Provider.of<PresenceProvider>(context, listen: false);
      presenceProvider.connectRealtime(_realtimeService!);
      AppLogger.i('PresenceProvider connecté au service temps réel', tag: 'MyApp');

      // Connecter NotificationService
      final notificationService = Provider.of<NotificationService>(context, listen: false);
      notificationService.connectRealtime(_realtimeService!);
      AppLogger.i('NotificationService connecté au service temps réel', tag: 'MyApp');
    } catch (e, stackTrace) {
      AppLogger.e('Erreur lors de la connexion des providers au temps réel', error: e, stackTrace: stackTrace, tag: 'MyApp');
    }
  }

  @override
  void dispose() {
    _realtimeService?.disconnect();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // Récupération des dépendances depuis GetIt
    final friendsRepository = sl<FriendsRepositoryImpl>();
    final notificationDataSource = sl<NotificationRemoteDataSource>();
    final secureStorage = sl<SecureStorage>();
    final eventRemoteDataSource = sl<EventRemoteDataSource>();

    // Log lors de la construction de l'application
    AppLogger.i(
      "Construction de l'application avec user : ${widget.user.toString()}",
      tag: 'MyApp',
    );

    return MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (_) => UserProvider()..setUser(widget.user),
        ),
        ChangeNotifierProvider(
          create: (_) => FriendsProvider(friendsRepository: friendsRepository),
        ),
        ChangeNotifierProvider(
          create: (_) => PresenceProvider(),
        ),
        ChangeNotifierProvider(
          create: (_) => ThemeProvider(),
        ),
        ChangeNotifierProvider(
          create: (_) => NotificationService(notificationDataSource, secureStorage)
            ..initialize(),
        ),
        BlocProvider(
          create: (context) => sl<EventBloc>(),
        ),
      ],
      child: Consumer<ThemeProvider>(
        builder: (context, themeProvider, _) {
          // Connecter les providers au service temps réel après leur création
          if (_isInitialized && _realtimeService != null) {
            WidgetsBinding.instance.addPostFrameCallback((_) {
              _connectProvidersToRealtime(context);
            });
          }

          final materialApp = MaterialApp(
            title: 'AfterWork',
            theme: themeProvider.currentTheme,
            onGenerateRoute: AppRouter(
              eventRemoteDataSource: eventRemoteDataSource,
              userId: widget.user.userId,
              userFirstName: widget.user.userFirstName,
              userLastName: widget.user.userLastName,
            ).generateRoute,
            initialRoute: '/',
          );

          // Wrapper avec RealtimeNotificationHandler si le service est initialisé
          if (_isInitialized && _realtimeService != null) {
            return RealtimeNotificationHandler(
              realtimeService: _realtimeService!,
              child: materialApp,
            );
          }

          return materialApp;
        },
      ),
    );
  }
}

