import 'dart:async';
import 'dart:math' as math;

import 'package:em2rp/providers/local_user_provider.dart';
import 'package:em2rp/providers/event_provider.dart';
import 'package:em2rp/utils/performance_monitor.dart';
import 'package:flutter/material.dart';
import 'package:em2rp/views/widgets/nav/custom_app_bar.dart';
import 'package:em2rp/views/widgets/nav/main_drawer.dart';
import 'package:em2rp/views/widgets/common/startup_splash_screen.dart';
import 'package:provider/provider.dart';
import 'package:table_calendar/table_calendar.dart';
import 'package:em2rp/models/event_model.dart';
import 'package:em2rp/views/widgets/calendar_widgets/event_details.dart';
import 'package:intl/intl.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:em2rp/views/widgets/calendar_widgets/month_view.dart';
import 'package:em2rp/views/widgets/calendar_widgets/week_view.dart';
import 'package:em2rp/views/event_add_page.dart';
import 'package:em2rp/views/widgets/calendar_widgets/mobile_calendar_view.dart';
import 'package:em2rp/views/widgets/calendar_widgets/user_filter_dropdown.dart';
import 'package:em2rp/utils/colors.dart';

class CalendarPage extends StatefulWidget {
  const CalendarPage({super.key});

  @override
  State<CalendarPage> createState() => _CalendarPageState();
}

class _CalendarPageState extends State<CalendarPage> {
  static const double _minDetailsPaneFraction = 0.25;
  static const double _maxDetailsPaneFraction = 0.5;
  static const double _desktopResizeHandleWidth = 12;
  static const double _minCalendarPaneWidth = 480;
  static const double _minDetailsPaneWidth = 320;

  CalendarFormat _calendarFormat = CalendarFormat.month;
  DateTime _focusedDay = DateTime.now();
  DateTime? _selectedDay;
  EventModel? _selectedEvent;
  bool _calendarCollapsed = false;
  int _selectedEventIndex = 0;
  String?
      _selectedUserId; // Filtre par utilisateur (null = tous les événements)
  final TextEditingController _searchController = TextEditingController();
  Timer? _searchDebounce;
  List<EventModel> _searchResults = [];
  String _searchQuery = '';
  String? _searchError;
  bool _isSearching = false;
  int _searchRequestId = 0;
  bool _isMobileSearchVisible = false;
  bool _isRefreshing = false;
  final ValueNotifier<double> _detailsPaneFraction = ValueNotifier<double>(0.35);
  String? _lastLoadedUserId;
  bool _initialLoadScheduled = false;

  @override
  void initState() {
    super.initState();
    initializeDateFormatting('fr_FR', null);
    // Charger les événements du mois courant après le premier build
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _loadCurrentMonthEvents();
    });
  }

  /// Charge les événements du mois courant avec lazy loading
  Future<void> _loadCurrentMonthEvents() async {
    PerformanceMonitor.start('CalendarPage.loadCurrentMonthEvents');

    final localAuthProvider =
        Provider.of<LocalUserProvider>(context, listen: false);
    final eventProvider = Provider.of<EventProvider>(context, listen: false);
    final userId = localAuthProvider.uid;
    final canViewAllEvents = localAuthProvider.hasPermission('view_all_events');

    if (userId != null) {
      print(
          '[CalendarPage] Loading events for ${_focusedDay.year}-${_focusedDay.month}');

      await eventProvider.loadMonthEvents(
        userId,
        _focusedDay.year,
        _focusedDay.month,
        canViewAllEvents: canViewAllEvents,
      );

      // Précharger les mois adjacents en arrière-plan
      eventProvider.preloadAdjacentMonths(
        userId,
        _focusedDay.year,
        _focusedDay.month,
        canViewAllEvents: canViewAllEvents,
      );

      if (mounted) {
        PerformanceMonitor.start('CalendarPage.selectDefaultEvent');
        _selectDefaultEvent();
        PerformanceMonitor.end('CalendarPage.selectDefaultEvent');
      }
    }

    PerformanceMonitor.end('CalendarPage.loadCurrentMonthEvents');
  }

  /// Vide le cache et recharge les événements du mois courant
  Future<void> _refreshEvents() async {
    if (_isRefreshing) return;
    setState(() => _isRefreshing = true);
    try {
      final eventProvider = Provider.of<EventProvider>(context, listen: false);
      eventProvider.clearAllCache();
      await _loadCurrentMonthEvents();
    } finally {
      if (mounted) setState(() => _isRefreshing = false);
    }
  }

  void _scheduleInitialEventsLoad(String? userId) {
    if (userId == null || userId == _lastLoadedUserId || _initialLoadScheduled) {
      return;
    }

    _initialLoadScheduled = true;
    WidgetsBinding.instance.addPostFrameCallback((_) async {
      try {
        if (!mounted) return;
        if (_lastLoadedUserId == userId) return;
        await _loadCurrentMonthEvents();
        _lastLoadedUserId = userId;
      } finally {
        _initialLoadScheduled = false;
      }
    });
  }

  /// Sélectionne automatiquement l'événement le plus proche de maintenant
  void _selectDefaultEvent() {
    final eventProvider = Provider.of<EventProvider>(context, listen: false);
    final events = eventProvider.events;

    if (events.isEmpty) return;

    final now = DateTime.now();

    // Trouver les événements d'aujourd'hui
    final todayEvents = events.where((e) {
      final start = e.startDateTime;
      return start.year == now.year &&
          start.month == now.month &&
          start.day == now.day;
    }).toList()
      ..sort((a, b) => a.startDateTime.compareTo(b.startDateTime));

    EventModel? selected;
    DateTime? selectedDay;

    if (todayEvents.isNotEmpty) {
      selected = todayEvents[0];
      selectedDay = DateTime(now.year, now.month, now.day);
    } else {
      // Chercher le prochain événement à venir
      final futureEvents = events
          .where((e) => e.startDateTime.isAfter(now))
          .toList()
        ..sort((a, b) => a.startDateTime.compareTo(b.startDateTime));

      if (futureEvents.isNotEmpty) {
        selected = futureEvents[0];
        final start = selected.startDateTime;
        selectedDay = DateTime(start.year, start.month, start.day);
      } else {
        // Aucun événement à venir, prendre le plus récent
        final sortedEvents = events.toList()
          ..sort((a, b) => b.startDateTime.compareTo(a.startDateTime));
        selected = sortedEvents.first;
        final start = selected.startDateTime;
        selectedDay = DateTime(start.year, start.month, start.day);
      }
    }

    if (mounted) {
      setState(() {
        _selectedDay = selectedDay;
        _focusedDay = selectedDay!;
        _selectedEventIndex = 0;
        _selectedEvent = selected;
      });
    }
  }

  Future<void> _loadEvents() async {
    final localAuthProvider =
        Provider.of<LocalUserProvider>(context, listen: false);
    final eventProvider = Provider.of<EventProvider>(context, listen: false);
    final userId = localAuthProvider.uid;
    final canViewAllEvents = localAuthProvider.hasPermission('view_all_events');

    if (userId != null) {
      await eventProvider.loadUserEvents(userId,
          canViewAllEvents: canViewAllEvents);
    }
  }

  @override
  void dispose() {
    _searchDebounce?.cancel();
    _searchController.dispose();
    _detailsPaneFraction.dispose();
    super.dispose();
  }

  /// Filtre les événements selon l'utilisateur sélectionné (si filtre actif).
  List<EventModel> _filterEventsByUser(List<EventModel> allEvents) {
    if (_selectedUserId == null) {
      return allEvents; // Pas de filtre, retourner tous les événements
    }

    // Filtrer les événements où l'utilisateur sélectionné fait partie de la workforce
    return allEvents.where((event) {
      return event.workforce.any((worker) {
        if (worker is String) {
          return worker == _selectedUserId;
        }
        // Si c'est une DocumentReference, on ne peut pas facilement comparer
        // On suppose que les données sont chargées correctement en String
        return false;
      });
    }).toList();
  }

  bool _isSameDay(DateTime left, DateTime right) {
    return left.year == right.year &&
        left.month == right.month &&
        left.day == right.day;
  }

  List<EventModel> _getEventsForDay(
    List<EventModel> events,
    DateTime? day, {
    EventModel? selectedEvent,
  }) {
    if (day == null) {
      return [];
    }

    final dayEvents = events
        .where((event) => _isSameDay(event.startDateTime, day))
        .toList()
      ..sort((a, b) => a.startDateTime.compareTo(b.startDateTime));

    if (selectedEvent != null &&
        _isSameDay(selectedEvent.startDateTime, day) &&
        !dayEvents.any((event) => event.id == selectedEvent.id)) {
      dayEvents.add(selectedEvent);
      dayEvents.sort((a, b) => a.startDateTime.compareTo(b.startDateTime));
    }

    return dayEvents;
  }

  List<EventModel> _getDetailsEvents(List<EventModel> events) {
    final mergedEvents = [...events];

    if (_selectedEvent != null &&
        !mergedEvents.any((event) => event.id == _selectedEvent!.id)) {
      mergedEvents.add(_selectedEvent!);
    }

    mergedEvents.sort((a, b) => a.startDateTime.compareTo(b.startDateTime));
    return mergedEvents;
  }

  String _formatSearchResultDate(DateTime dateTime) {
    return DateFormat('EEE d MMM yyyy • HH:mm', 'fr_FR').format(dateTime);
  }

  Color _getStatusColor(EventStatus status) {
    switch (status) {
      case EventStatus.confirmed:
        return Colors.green;
      case EventStatus.canceled:
        return Colors.red;
      case EventStatus.waitingForApproval:
      default:
        return Colors.amber;
    }
  }

  /// Combine uniquement le filtre utilisateur avec la vue calendrier.
  List<EventModel> _getFilteredEvents(List<EventModel> allEvents) {
    return _filterEventsByUser(allEvents);
  }

  void _cancelPendingSearch() {
    _searchDebounce?.cancel();
    _searchDebounce = null;
  }

  void _scheduleSearch(String value) {
    _cancelPendingSearch();

    _searchDebounce = Timer(const Duration(milliseconds: 300), () {
      _runSearch(value);
    });
  }

  void _onSearchChanged(String value) {
    final isMobile = MediaQuery.of(context).size.width < 600;

    if (isMobile && value.isNotEmpty && !_isMobileSearchVisible) {
      setState(() {
        _isMobileSearchVisible = true;
      });
    }

    setState(() {
      _searchQuery = value;
    });

    if (value.trim().isEmpty) {
      _cancelPendingSearch();
      setState(() {
        _searchResults = [];
        _searchError = null;
        _isSearching = false;
      });
      return;
    }

    _scheduleSearch(value);
  }

  void _clearSearch() {
    _cancelPendingSearch();

    if (_searchController.text.isEmpty) {
      return;
    }

    _searchController.clear();
    setState(() {
      _searchQuery = '';
      _searchResults = [];
      _searchError = null;
      _isSearching = false;
    });
  }

  Future<void> _runSearch(String value) async {
    final query = value.trim();
    if (query.isEmpty) {
      return;
    }

    final localUserProvider = context.read<LocalUserProvider>();
    final userId = localUserProvider.uid;
    if (userId == null) {
      return;
    }

    final searchId = ++_searchRequestId;
    setState(() {
      _isSearching = true;
      _searchError = null;
      _searchResults = [];
    });

    try {
      final eventProvider = context.read<EventProvider>();
      final results = await eventProvider.searchEvents(
        userId: userId,
        query: query,
      );

      if (!mounted) {
        return;
      }

      if (_searchQuery.trim() != query) {
        return;
      }

      if (searchId != _searchRequestId) {
        return;
      }

      setState(() {
        _searchResults = results;
        _searchError = null;
        _isSearching = false;
      });
    } catch (e) {
      if (!mounted || _searchQuery.trim() != query) {
        return;
      }

      setState(() {
        _searchResults = [];
        _searchError = 'Erreur lors de la recherche : $e';
        _isSearching = false;
      });
    }
  }

  Widget _buildDesktopFiltersBar({required bool canViewAllUserEvents}) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
      color: Colors.grey[100],
      child: Row(
        children: [
          Expanded(
            child: TextField(
              controller: _searchController,
              onChanged: _onSearchChanged,
              decoration: InputDecoration(
                hintText: 'Rechercher (titre, description, lieu)',
                prefixIcon: const Icon(Icons.search, color: AppColors.rouge),
                suffixIcon: _searchQuery.isNotEmpty
                    ? IconButton(
                        tooltip: 'Effacer la recherche',
                        icon: const Icon(Icons.close),
                        onPressed: _clearSearch,
                      )
                    : null,
                isDense: true,
                filled: true,
                fillColor: Colors.white,
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(10),
                  borderSide: BorderSide.none,
                ),
              ),
            ),
          ),
          if (canViewAllUserEvents) ...[
            const SizedBox(width: 12),
            _buildCompactUserFilter(),
          ],
        ],
      ),
    );
  }

  Widget _buildCompactUserFilter() {
    return ConstrainedBox(
      constraints: const BoxConstraints(maxWidth: 300),
      child: Row(
          children: [
            Expanded(
              child: UserFilterDropdown(
                selectedUserId: _selectedUserId,
                onUserSelected: (userId) {
                  setState(() {
                    _selectedUserId = userId;
                  });
                },
              ),
            ),
          ],
        ),
    );
  }

  Widget _buildMobileSearchBar() {
    return Container(
      color: Colors.grey[100],
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
      child: Column(
        children: [
          Row(
            children: [
              IconButton(
                icon: Icon(
                  _isMobileSearchVisible ? Icons.search_off : Icons.search,
                  color: AppColors.rouge,
                ),
                tooltip: _isMobileSearchVisible
                    ? 'Masquer la recherche'
                    : 'Afficher la recherche',
                onPressed: () {
                  setState(() {
                    _isMobileSearchVisible = !_isMobileSearchVisible;
                  });
                },
              ),
              Expanded(
                child: Text(
                  _searchQuery.isEmpty
                      ? 'Rechercher un événement'
                      : 'Recherche active',
                  style: const TextStyle(
                    fontSize: 14,
                    fontWeight: FontWeight.w500,
                  ),
                ),
              ),
              if (_searchQuery.isNotEmpty)
                IconButton(
                  icon: const Icon(Icons.close),
                  tooltip: 'Effacer la recherche',
                  onPressed: _clearSearch,
                ),
            ],
          ),
          AnimatedSwitcher(
            duration: const Duration(milliseconds: 200),
            child: _isMobileSearchVisible
                ? Padding(
                    key: const ValueKey('mobile-search-visible'),
                    padding: const EdgeInsets.only(top: 4, left: 8, right: 8),
                    child: TextField(
                      controller: _searchController,
                      onChanged: _onSearchChanged,
                      decoration: InputDecoration(
                        hintText: 'Titre, description ou lieu',
                        prefixIcon:
                            const Icon(Icons.search, color: AppColors.rouge),
                        isDense: true,
                        filled: true,
                        fillColor: Colors.white,
                        border: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(10),
                          borderSide: BorderSide.none,
                        ),
                      ),
                    ),
                  )
                : const SizedBox.shrink(
                    key: ValueKey('mobile-search-hidden'),
                  ),
          ),
        ],
      ),
    );
  }

  Widget _buildSearchResultsPanel({required bool isMobile}) {
    final hasQuery = _searchQuery.trim().isNotEmpty;

    if (!hasQuery && !_isSearching && _searchError == null) {
      return const SizedBox.shrink();
    }

    final panelPadding = EdgeInsets.symmetric(
      horizontal: isMobile ? 8 : 16,
      vertical: 8,
    );

    return Container(
      width: double.infinity,
      padding: panelPadding,
      color: Colors.grey[50],
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisSize: MainAxisSize.min,
        children: [
          Row(
            children: [
              const Icon(Icons.manage_search, color: AppColors.rouge, size: 20),
              const SizedBox(width: 8),
              Expanded(
                child: Text(
                  hasQuery
                      ? 'Résultats pour "$_searchQuery"'
                      : 'Recherche d’événements',
                  style: const TextStyle(
                    fontWeight: FontWeight.w600,
                  ),
                ),
              ),
              if (_isSearching)
                const SizedBox(
                  width: 18,
                  height: 18,
                  child: CircularProgressIndicator(strokeWidth: 2),
                ),
            ],
          ),
          if (_searchError != null) ...[
            const SizedBox(height: 8),
            Text(
              _searchError!,
              style: const TextStyle(color: Colors.red),
            ),
          ] else if (!hasQuery) ...[
            const SizedBox(height: 8),
            Text(
              'Saisissez un titre, une description ou un lieu pour lancer la recherche.',
              style: TextStyle(color: Colors.grey.shade700),
            ),
          ] else if (!_isSearching) ...[
            const SizedBox(height: 8),
            if (_searchResults.isEmpty)
              Text(
                'Aucun résultat trouvé.',
                style: TextStyle(color: Colors.grey.shade700),
              )
            else
              ConstrainedBox(
                constraints: BoxConstraints(
                  maxHeight: isMobile ? 240 : 280,
                ),
                child: ListView.builder(
                  shrinkWrap: true,
                  itemCount: _searchResults.length,
                  physics: const ClampingScrollPhysics(),
                  // ✅ prototypeItem : les résultats ont une hauteur variable
                  //    selon la présence du champ adresse (~56px sans, ~70px avec).
                  //    prototypeItem à 72px (cas avec adresse + padding) pour
                  //    que Flutter estime correctement la hauteur scrollable.
                  //    ListView.separated ne supporte pas itemExtent/prototypeItem,
                  //    d'où la conversion en ListView.builder avec séparateur intégré.
                  prototypeItem: const SizedBox(height: 72),
                  itemBuilder: (context, index) {
                    final event = _searchResults[index];
                    final isSelected = _selectedEvent?.id == event.id;
                    final isLast = index == _searchResults.length - 1;

                    return Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        Material(
                          color: isSelected
                              ? AppColors.rouge.withOpacity(0.08)
                              : Colors.white,
                          borderRadius: BorderRadius.circular(12),
                          child: InkWell(
                            borderRadius: BorderRadius.circular(12),
                            onTap: () => _onSearchResultSelected(event),
                            child: Padding(
                              padding: const EdgeInsets.all(12),
                              child: Row(
                                children: [
                                  Container(
                                    width: 10,
                                    height: 10,
                                    decoration: BoxDecoration(
                                      color: _getStatusColor(event.status),
                                      shape: BoxShape.circle,
                                    ),
                                  ),
                                  const SizedBox(width: 12),
                                  Expanded(
                                    child: Column(
                                      crossAxisAlignment: CrossAxisAlignment.start,
                                      children: [
                                        Text(
                                          event.name,
                                          maxLines: 1,
                                          overflow: TextOverflow.ellipsis,
                                          style: const TextStyle(
                                            fontWeight: FontWeight.w600,
                                          ),
                                        ),
                                        const SizedBox(height: 4),
                                        Text(
                                          _formatSearchResultDate(
                                              event.startDateTime),
                                          style: TextStyle(
                                            color: Colors.grey.shade700,
                                            fontSize: 12,
                                          ),
                                        ),
                                        if (event.address.isNotEmpty) ...[
                                          const SizedBox(height: 2),
                                          Text(
                                            event.address,
                                            maxLines: 1,
                                            overflow: TextOverflow.ellipsis,
                                            style: TextStyle(
                                              color: Colors.grey.shade600,
                                              fontSize: 12,
                                            ),
                                          ),
                                        ],
                                      ],
                                    ),
                                  ),
                                  const SizedBox(width: 8),
                                  const Icon(Icons.chevron_right,
                                      color: Colors.grey),
                                ],
                              ),
                            ),
                          ),
                        ),
                        if (!isLast) const SizedBox(height: 8),
                      ],
                    );
                  },
                ),
              ),
          ],
        ],
      ),
    );
  }

  Future<void> _onSearchResultSelected(EventModel event) async {
    final localUserProvider = context.read<LocalUserProvider>();
    final eventProvider = context.read<EventProvider>();
    final userId = localUserProvider.uid;

    if (userId == null) {
      return;
    }

    final canViewAllEvents = localUserProvider.hasPermission('view_all_events');
    final selectedDay = DateTime(
      event.startDateTime.year,
      event.startDateTime.month,
      event.startDateTime.day,
    );
    final shouldLoadMonth = _focusedDay.year != event.startDateTime.year ||
        _focusedDay.month != event.startDateTime.month ||
        eventProvider.events.isEmpty;

    if (shouldLoadMonth) {
      await eventProvider.loadMonthEvents(
        userId,
        event.startDateTime.year,
        event.startDateTime.month,
        canViewAllEvents: canViewAllEvents,
      );

      eventProvider.preloadAdjacentMonths(
        userId,
        event.startDateTime.year,
        event.startDateTime.month,
        canViewAllEvents: canViewAllEvents,
      );
    }

    if (!mounted) {
      return;
    }

    final eventsForSelectedDay = _getEventsForDay(
      eventProvider.events,
      selectedDay,
      selectedEvent: event,
    );
    final isMobile = MediaQuery.of(context).size.width < 600;

    setState(() {
      _focusedDay = selectedDay;
      _selectedDay = selectedDay;
      _selectedEvent = event;
      _selectedEventIndex =
          eventsForSelectedDay.indexWhere((e) => e.id == event.id);
      if (_selectedEventIndex < 0) {
        _selectedEventIndex = 0;
      }
      _calendarCollapsed = false;
      if (isMobile) {
        _isMobileSearchVisible = true;
      }
    });
  }

  void _changeWeek(int delta) {
    setState(() {
      _focusedDay = _focusedDay.add(Duration(days: 7 * delta));
    });
  }

  double _clampDetailsPaneFraction(double fraction, double totalWidth) {
    if (totalWidth <= 0) {
      return fraction.clamp(_minDetailsPaneFraction, _maxDetailsPaneFraction);
    }

    final minFractionFromPixels = _minDetailsPaneWidth / totalWidth;
    final maxFractionFromPixels =
        (totalWidth - _desktopResizeHandleWidth - _minCalendarPaneWidth) /
            totalWidth;

    final minFraction =
        math.max(_minDetailsPaneFraction, minFractionFromPixels);
    final maxFraction =
        math.min(_maxDetailsPaneFraction, maxFractionFromPixels);

    if (maxFraction < minFraction) {
      return fraction.clamp(_minDetailsPaneFraction, _maxDetailsPaneFraction);
    }

    return fraction.clamp(minFraction, maxFraction);
  }

  Widget _buildDesktopDetailsPane(List<EventModel> filteredEvents) {
    if (_selectedEvent != null) {
      final detailsEvents = _getDetailsEvents(filteredEvents);

      return EventDetails(
        event: _selectedEvent!,
        selectedDate: _selectedDay,
        events: detailsEvents,
        onSelectEvent: (event, date) {
          setState(() {
            _selectedEvent = event;
            _selectedDay = date;
          });
        },
      );
    }

    return Center(
      child: _selectedDay != null
          ? const Text('Aucun événement ne démarre à cette date')
          : const Text('Sélectionnez un événement pour voir les détails'),
    );
  }

  Widget _buildDesktopResizeHandle(double totalWidth) {
    return MouseRegion(
      cursor: SystemMouseCursors.resizeLeftRight,
      child: GestureDetector(
        behavior: HitTestBehavior.opaque,
        onHorizontalDragUpdate: (details) {
          _detailsPaneFraction.value = _clampDetailsPaneFraction(
            _detailsPaneFraction.value - (details.delta.dx / totalWidth),
            totalWidth,
          );
        },
        child: SizedBox(
          width: _desktopResizeHandleWidth,
          child: Center(
            child: Container(
              width: 4,
              margin: const EdgeInsets.symmetric(vertical: 16),
              decoration: BoxDecoration(
                color: Colors.grey.shade300,
                borderRadius: BorderRadius.circular(999),
              ),
            ),
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final eventProvider = Provider.of<EventProvider>(context);
    final localUserProvider = Provider.of<LocalUserProvider>(context);
    _scheduleInitialEventsLoad(localUserProvider.uid);
    final canCreateEvents = localUserProvider.hasPermission('create_events');
    final canViewAllUserEvents =
        localUserProvider.hasPermission('view_all_user_events');
    final isMobile = MediaQuery.of(context).size.width < 600;
    final showSearchResults =
        _searchQuery.trim().isNotEmpty || _isSearching || _searchError != null;

    // Appliquer le filtre utilisateur si actif
    final filteredEvents = _getFilteredEvents(eventProvider.events);

    // Debug logs
    print(
        '[CalendarPage.build] Total events: ${eventProvider.events.length}, Filtered: ${filteredEvents.length}');
    if (eventProvider.events.isNotEmpty) {
      print(
          '[CalendarPage.build] First event: ${eventProvider.events.first.name} at ${eventProvider.events.first.startDateTime}');
    }

    if (eventProvider.isLoading) {
      return const StartupSplashScreen(message: 'Chargement des événements...');
    }

    return Scaffold(
      appBar: CustomAppBar(
        title: "Calendrier",
        actions: [
          if (_isRefreshing)
            const Padding(
              padding: EdgeInsets.symmetric(horizontal: 12),
              child: SizedBox(
                width: 20,
                height: 20,
                child: CircularProgressIndicator(
                  strokeWidth: 2,
                  color: Colors.white,
                ),
              ),
            )
          else
            IconButton(
              icon: const Icon(Icons.refresh, color: Colors.white),
              tooltip: 'Mettre à jour les événements',
              onPressed: _refreshEvents,
            ),
        ],
      ),
      drawer: const MainDrawer(currentPage: '/calendar'),
      body: Column(
        children: [
          if (isMobile)
            _buildMobileSearchBar()
          else
            _buildDesktopFiltersBar(canViewAllUserEvents: canViewAllUserEvents),
          if (showSearchResults) _buildSearchResultsPanel(isMobile: isMobile),
          // Corps du calendrier
          Expanded(
            child: isMobile
                ? _buildMobileLayout(filteredEvents)
                : _buildDesktopLayout(filteredEvents),
          ),
        ],
      ),
      floatingActionButton: canCreateEvents
          ? FloatingActionButton(
              backgroundColor: Colors.white,
              onPressed: () {
                Navigator.of(context).push(
                  MaterialPageRoute(
                    builder: (context) => EventAddEditPage(
                      selectedDate: _selectedDay ?? DateTime.now(),
                    ),
                  ),
                );
              },
              tooltip: 'Ajouter un événement',
              child: const Icon(Icons.add, color: Colors.red),
            )
          : null,
    );
  }

  Widget _buildDesktopLayout(List<EventModel> filteredEvents) {
    return LayoutBuilder(
      builder: (context, constraints) {
        final totalWidth = constraints.maxWidth;
        return ValueListenableBuilder<double>(
          valueListenable: _detailsPaneFraction,
          builder: (context, fraction, child) {
            final detailsPaneFraction =
                _clampDetailsPaneFraction(fraction, totalWidth);
            final detailsWidth = totalWidth * detailsPaneFraction;
            final calendarWidth =
                totalWidth - _desktopResizeHandleWidth - detailsWidth;

            return Row(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                SizedBox(
                  width: calendarWidth,
                  child: _buildCalendar(filteredEvents),
                ),
                _buildDesktopResizeHandle(totalWidth),
                SizedBox(
                  width: detailsWidth,
                  child: _buildDesktopDetailsPane(filteredEvents),
                ),
              ],
            );
          },
        );
      },
    );
  }

  Widget _buildMobileLayout(List<EventModel> filteredEvents) {
    final eventsForSelectedDay = _getEventsForDay(
      filteredEvents,
      _selectedDay,
      selectedEvent: _selectedEvent,
    );
    final hasEvents = eventsForSelectedDay.isNotEmpty;
    final selectedEventIndex = _selectedEvent == null
        ? -1
        : eventsForSelectedDay
            .indexWhere((event) => event.id == _selectedEvent!.id);
    final currentEvent = hasEvents && selectedEventIndex >= 0
        ? eventsForSelectedDay[selectedEventIndex]
        : hasEvents && _selectedEventIndex < eventsForSelectedDay.length
            ? eventsForSelectedDay[_selectedEventIndex]
            : null;

    return LayoutBuilder(
      builder: (context, constraints) {
        final maxHeight = constraints.maxHeight;

        // GESTURE DETECTOR pour swipe vertical (plier/déplier) et horizontal (mois)
        return GestureDetector(
          onVerticalDragEnd: (details) {
            if (details.primaryVelocity != null) {
              if (details.primaryVelocity! < -200) {
                // Swipe vers le haut : plier
                setState(() {
                  _calendarCollapsed = true;
                });
              } else if (details.primaryVelocity! > 200) {
                // Swipe vers le bas : déplier
                setState(() {
                  _calendarCollapsed = false;
                });
              }
            }
          },
          onHorizontalDragEnd: (details) {
            if (details.primaryVelocity != null) {
              if (details.primaryVelocity! < -200) {
                // Swipe gauche : mois suivant
                final newMonth =
                    DateTime(_focusedDay.year, _focusedDay.month + 1, 1);
                setState(() {
                  _focusedDay = newMonth;
                });
                print(
                    '[CalendarPage] Month changed to ${newMonth.year}-${newMonth.month}');
                _loadCurrentMonthEvents();
              } else if (details.primaryVelocity! > 200) {
                // Swipe droite : mois précédent
                final newMonth =
                    DateTime(_focusedDay.year, _focusedDay.month - 1, 1);
                setState(() {
                  _focusedDay = newMonth;
                });
                print(
                    '[CalendarPage] Month changed to ${newMonth.year}-${newMonth.month}');
                _loadCurrentMonthEvents();
              }
            }
          },
          child: Stack(
            children: [
              // Calendrier + détails en dessous
              AnimatedPositioned(
                duration: const Duration(milliseconds: 400),
                curve: Curves.easeInOut,
                top: _calendarCollapsed ? -maxHeight : 0, // cache le calendrier en haut
                left: 0,
                right: 0,
                height: _calendarCollapsed ? 0 : null,
                child: SizedBox(
                  height: maxHeight,
                  child: Column(
                    children: [
                      _buildMonthHeader(context),
                      if (!_calendarCollapsed)
                        // Ajout d'un GestureDetector pour swipe horizontal sur le calendrier
                        GestureDetector(
                          onHorizontalDragEnd: (details) {
                            if (details.primaryVelocity != null) {
                              if (details.primaryVelocity! < -200) {
                                // Swipe gauche : mois suivant
                                final newMonth = DateTime(
                                    _focusedDay.year, _focusedDay.month + 1, 1);
                                setState(() {
                                  _focusedDay = newMonth;
                                });
                                print(
                                    '[CalendarPage] Month changed to ${newMonth.year}-${newMonth.month}');
                                _loadCurrentMonthEvents();
                              } else if (details.primaryVelocity! > 200) {
                                // Swipe droite : mois précédent
                                final newMonth = DateTime(
                                    _focusedDay.year, _focusedDay.month - 1, 1);
                                setState(() {
                                  _focusedDay = newMonth;
                                });
                                print(
                                    '[CalendarPage] Month changed to ${newMonth.year}-${newMonth.month}');
                                _loadCurrentMonthEvents();
                              }
                            }
                          },
                          child: MobileCalendarView(
                            focusedDay: _focusedDay,
                            selectedDay: _selectedDay,
                            events: filteredEvents,
                            onDaySelected: (day) {
                              final eventsForDay = filteredEvents
                                  .where((e) =>
                                      e.startDateTime.year == day.year &&
                                      e.startDateTime.month == day.month &&
                                      e.startDateTime.day == day.day)
                                  .toList()
                                ..sort((a, b) =>
                                    a.startDateTime.compareTo(b.startDateTime));
                              setState(() {
                                _selectedDay = day;
                                _calendarCollapsed = false;
                                _selectedEventIndex = 0;
                                _selectedEvent = eventsForDay.isNotEmpty
                                    ? eventsForDay[0]
                                    : null;
                              });
                            },
                          ),
                        ),
                      Expanded(
                        child: hasEvents
                            // Ajout d'un GestureDetector pour swipe horizontal sur le détail événement
                            ? GestureDetector(
                                onHorizontalDragEnd: (details) {
                                  if (details.primaryVelocity != null) {
                                    if (details.primaryVelocity! < -200) {
                                      // Swipe gauche : événement suivant
                                      if (_selectedEventIndex <
                                          eventsForSelectedDay.length - 1) {
                                        setState(() {
                                          _selectedEventIndex++;
                                          _selectedEvent = eventsForSelectedDay[
                                              _selectedEventIndex];
                                        });
                                      }
                                    } else if (details.primaryVelocity! > 200) {
                                      // Swipe droite : événement précédent
                                      if (_selectedEventIndex > 0) {
                                        setState(() {
                                          _selectedEventIndex--;
                                          _selectedEvent = eventsForSelectedDay[
                                              _selectedEventIndex];
                                        });
                                      }
                                    }
                                  }
                                },
                                child: EventDetails(
                                  event: eventsForSelectedDay[_selectedEventIndex],
                                  selectedDate: _selectedDay,
                                  events: eventsForSelectedDay,
                                  onSelectEvent: (event, date) {
                                    final idx = eventsForSelectedDay
                                        .indexWhere((e) => e.id == event.id);
                                    setState(() {
                                      _selectedEventIndex = idx >= 0 ? idx : 0;
                                      _selectedEvent = event;
                                    });
                                  },
                                ),
                              )
                            : Center(
                                child: Text(
                                    'Aucun événement ne démarre à cette date')),
                      ),
                    ],
                  ),
                ),
              ),
              // Vue détail (prend tout l'espace quand calendrier cache)
              if (_calendarCollapsed && _selectedDay != null)
                AnimatedPositioned(
                  duration: const Duration(milliseconds: 400),
                  curve: Curves.easeInOut,
                  top: _calendarCollapsed ? 0 : maxHeight,
                  left: 0,
                  right: 0,
                  bottom: 0,
                  child: SizedBox(
                    height: maxHeight,
                    child: Column(
                      children: [
                        _buildMonthHeader(context),
                        Expanded(
                          child: Stack(
                            children: [
                              if (currentEvent != null)
                                // Ajout d'un GestureDetector pour swipe horizontal sur le détail événement
                                GestureDetector(
                                  onHorizontalDragEnd: (details) {
                                    if (details.primaryVelocity != null) {
                                      if (details.primaryVelocity! < -200) {
                                        // Swipe gauche : événement suivant
                                        if (_selectedEventIndex <
                                            eventsForSelectedDay.length - 1) {
                                          setState(() {
                                            _selectedEventIndex++;
                                            _selectedEvent = eventsForSelectedDay[
                                                _selectedEventIndex];
                                          });
                                        }
                                      } else if (details.primaryVelocity! > 200) {
                                        // Swipe droite : événement précédent
                                        if (_selectedEventIndex > 0) {
                                          setState(() {
                                            _selectedEventIndex--;
                                            _selectedEvent = eventsForSelectedDay[
                                                _selectedEventIndex];
                                          });
                                        }
                                      }
                                    }
                                  },
                                  child: EventDetails(
                                    event: currentEvent,
                                    selectedDate: _selectedDay,
                                    events: eventsForSelectedDay,
                                    onSelectEvent: (event, date) {
                                      final idx = eventsForSelectedDay
                                          .indexWhere((e) => e.id == event.id);
                                      setState(() {
                                        _selectedEventIndex = idx >= 0 ? idx : 0;
                                        _selectedEvent = event;
                                      });
                                    },
                                  ),
                                ),
                              if (!hasEvents)
                                const Center(
                                  child: Text(
                                      'Aucun événement ne démarre à cette date'),
                                ),
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
            ],
          ),
        );
      },
    );
  }

  Widget _buildMonthHeader(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(top: 8, bottom: 8),
      child: Row(
        children: [
          IconButton(
            icon: const Icon(Icons.chevron_left,
                color: AppColors.rouge, size: 28),
            onPressed: () {
              final newMonth =
                  DateTime(_focusedDay.year, _focusedDay.month - 1, 1);
              setState(() {
                _focusedDay = newMonth;
              });
              print(
                  '[CalendarPage] Month changed to ${newMonth.year}-${newMonth.month}');
              _loadCurrentMonthEvents();
            },
          ),
          Expanded(
            child: GestureDetector(
              onTap: () {
                setState(() {
                  _calendarCollapsed = !_calendarCollapsed;
                });
              },
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                mainAxisSize: MainAxisSize.min,
                children: [
                  Text(
                    _getMonthName(_focusedDay.month),
                    style: const TextStyle(
                      color: AppColors.rouge,
                      fontWeight: FontWeight.bold,
                      fontSize: 20,
                    ),
                  ),
                  const SizedBox(width: 6),
                  Icon(
                    _calendarCollapsed
                        ? Icons.keyboard_arrow_down
                        : Icons.keyboard_arrow_up,
                    color: AppColors.rouge,
                    size: 26,
                  ),
                ],
              ),
            ),
          ),
          IconButton(
            icon: const Icon(Icons.chevron_right,
                color: AppColors.rouge, size: 28),
            onPressed: () {
              final newMonth =
                  DateTime(_focusedDay.year, _focusedDay.month + 1, 1);
              setState(() {
                _focusedDay = newMonth;
              });
              print(
                  '[CalendarPage] Month changed to ${newMonth.year}-${newMonth.month}');
              _loadCurrentMonthEvents();
            },
          ),
        ],
      ),
    );
  }

  String _getMonthName(int month) {
    switch (month) {
      case 1:
        return 'Janvier';
      case 2:
        return 'Février';
      case 3:
        return 'Mars';
      case 4:
        return 'Avril';
      case 5:
        return 'Mai';
      case 6:
        return 'Juin';
      case 7:
        return 'Juillet';
      case 8:
        return 'Août';
      case 9:
        return 'Septembre';
      case 10:
        return 'Octobre';
      case 11:
        return 'Novembre';
      case 12:
        return 'Décembre';
      default:
        return '';
    }
  }

  Widget _buildCalendar(List<EventModel> filteredEvents) {
    if (_calendarFormat == CalendarFormat.week) {
      return WeekView(
        focusedDay: _focusedDay,
        events: filteredEvents,
        onWeekChange: _changeWeek,
        onEventSelected: (event) {
          setState(() {
            _selectedEvent = event;
            _selectedDay = event.startDateTime;
          });
        },
        onSwitchToMonth: () {
          setState(() {
            _calendarFormat = CalendarFormat.month;
          });
        },
        onDaySelected: (selectedDay) {
          final eventsForDay = filteredEvents
              .where((e) =>
                  e.startDateTime.year == selectedDay.year &&
                  e.startDateTime.month == selectedDay.month &&
                  e.startDateTime.day == selectedDay.day)
              .toList();
          eventsForDay
              .sort((a, b) => a.startDateTime.compareTo(b.startDateTime));
          setState(() {
            _selectedDay = selectedDay;
            if (eventsForDay.isNotEmpty) {
              _selectedEvent = eventsForDay.first;
            } else {
              _selectedEvent = null;
            }
          });
          if (eventsForDay.isEmpty) {
            ScaffoldMessenger.of(context).showSnackBar(
              const SnackBar(
                content: Text("Aucun événement ne démarre à cette date."),
                duration: Duration(seconds: 2),
              ),
            );
          }
        },
        selectedEvent: _selectedEvent,
      );
    } else {
      return MonthView(
        focusedDay: _focusedDay,
        selectedDay: _selectedDay,
        calendarFormat: _calendarFormat,
        events: filteredEvents,
        onDaySelected: (selectedDay, focusedDay) {
          final eventsForDay = filteredEvents
              .where((event) =>
                  event.startDateTime.year == selectedDay.year &&
                  event.startDateTime.month == selectedDay.month &&
                  event.startDateTime.day == selectedDay.day)
              .toList()
            ..sort((a, b) => a.startDateTime.compareTo(b.startDateTime));
          setState(() {
            _selectedDay = selectedDay;
            _focusedDay = focusedDay;
            if (eventsForDay.isNotEmpty) {
              _selectedEvent = eventsForDay.first;
            } else {
              _selectedEvent = null;
            }
          });
        },
        onFormatChanged: (format) {
          setState(() {
            _calendarFormat = format;
          });
        },
        onPageChanged: (focusedDay) {
          // Détecter si on a changé de mois
          final monthChanged = focusedDay.year != _focusedDay.year ||
              focusedDay.month != _focusedDay.month;

          setState(() {
            _focusedDay = focusedDay;
          });

          // Charger les événements du nouveau mois si nécessaire
          if (monthChanged) {
            print(
                '[CalendarPage] Month changed to ${focusedDay.year}-${focusedDay.month}');
            _loadCurrentMonthEvents();
          }
        },
        onEventSelected: (event) {
          setState(() {
            _selectedEvent = event;
          });
        },
      );
    }
  }
}
