import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:cloud_functions/cloud_functions.dart';
import 'package:em2rp/models/event_model.dart';
import 'package:em2rp/models/equipment_model.dart';
import 'package:em2rp/models/container_model.dart';
import 'package:em2rp/providers/equipment_provider.dart';
import 'package:em2rp/providers/container_provider.dart';
import 'package:em2rp/providers/event_provider.dart';
import 'package:em2rp/services/data_service.dart';
import 'package:em2rp/services/api_service.dart';
import 'package:em2rp/services/qr_code_processing_service.dart';
import 'package:em2rp/services/audio_feedback_service.dart';
import 'package:em2rp/services/smart_text_to_speech_service.dart';
import 'package:em2rp/services/equipment_service.dart';
import 'package:em2rp/services/event_preparation_service.dart';
import 'package:em2rp/views/widgets/equipment/equipment_checklist_item.dart' show EquipmentChecklistItem, ChecklistStep;
import 'package:em2rp/views/widgets/equipment/container_checklist_item.dart';
import 'package:em2rp/views/widgets/common/qr_code_scanner_dialog.dart';
import 'package:em2rp/views/widgets/event_preparation/code_not_found_dialog.dart';
import 'package:em2rp/views/widgets/event_preparation/add_equipment_to_event_dialog.dart';
import 'package:em2rp/utils/debug_log.dart';
import 'package:em2rp/views/widgets/equipment/missing_equipment_dialog.dart';
import 'package:em2rp/utils/colors.dart';
import 'package:em2rp/views/widgets/common/audio_diagnostic_button.dart';

/// Type d'étape de préparation
enum PreparationStep {
  preparation,    // Préparation dépôt
  loadingOutbound, // Chargement aller
  unloadingReturn, // Chargement retour (déchargement)
  return_,        // Retour dépôt
}

/// Page de préparation ou de retour d'un événement
class EventPreparationPage extends StatefulWidget {
  final EventModel initialEvent;

  const EventPreparationPage({
    super.key,
    required this.initialEvent,
  });

  @override
  State<EventPreparationPage> createState() => _EventPreparationPageState();
}

class _EventPreparationPageState extends State<EventPreparationPage> with SingleTickerProviderStateMixin {
  late AnimationController _animationController;
  late final DataService _dataService;
  late final QRCodeProcessingService _qrCodeService;

  final Map<String, EquipmentModel> _equipmentCache = {};
  final Map<String, ContainerModel> _containerCache = {};
  final Map<String, int> _returnedQuantities = {};

  // État local des validations (non sauvegardé jusqu'à la validation finale)
  final Map<String, bool> _localValidationState = {};

  // Gestion des quantités par étape
  final Map<String, int> _quantitiesAtPreparation = {};
  final Map<String, int> _quantitiesAtLoading = {};
  final Map<String, int> _quantitiesAtUnloading = {};
  final Map<String, int> _quantitiesAtReturn = {};

  bool _isLoading = true;
  bool _isValidating = false;
  bool _showSuccessAnimation = false;
  bool _loadSimultaneously = false; // Checkbox "charger en même temps"

  // Stockage de l'événement actuel
  late EventModel _currentEvent;

  // 🆕 Pour la saisie manuelle de codes
  final TextEditingController _manualCodeController = TextEditingController();
  final FocusNode _manualCodeFocusNode = FocusNode();

  // 🆕 File d'attente pour traiter les scans séquentiellement
  final List<String> _scanQueue = [];
  bool _isProcessingQueue = false;

  // Détermine l'étape actuelle selon le statut de l'événement
  PreparationStep get _currentStep {
    final prep = _currentEvent.preparationStatus ?? PreparationStatus.notStarted;
    final loading = _currentEvent.loadingStatus ?? LoadingStatus.notStarted;
    final unloading = _currentEvent.unloadingStatus ?? UnloadingStatus.notStarted;
    final returnStatus = _currentEvent.returnStatus ?? ReturnStatus.notStarted;

    // Logique stricte : on avance étape par étape
    // 1. Préparation dépôt
    if (prep != PreparationStatus.completed && prep != PreparationStatus.completedWithMissing) {
      return PreparationStep.preparation;
    }

    // 2. Chargement aller (après préparation complète)
    if (loading != LoadingStatus.completed && loading != LoadingStatus.completedWithMissing) {
      return PreparationStep.loadingOutbound;
    }

    // 3. Chargement retour (après chargement aller complet)
    if (unloading != UnloadingStatus.completed && unloading != UnloadingStatus.completedWithMissing) {
      return PreparationStep.unloadingReturn;
    }

    // 4. Retour dépôt (après déchargement complet)
    if (returnStatus != ReturnStatus.completed && returnStatus != ReturnStatus.completedWithMissing) {
      return PreparationStep.return_;
    }

    // Tout est terminé, par défaut on retourne à la préparation
    return PreparationStep.preparation;
  }

  @override
  void initState() {
    super.initState();
    _currentEvent = widget.initialEvent;
    _dataService = DataService(FirebaseFunctionsApiService());
    _qrCodeService = QRCodeProcessingService();
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 500),
    );

    // Initialiser le service de synthèse vocale hybride
    SmartTextToSpeechService.initialize();

    // Initialiser et débloquer l'audio (pour éviter les problèmes d'autoplay)
    AudioFeedbackService.unlockAudio();

    // Vérification de sécurité et chargement après le premier frame
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (_isCurrentStepCompleted()) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(
            content: Text('Cette étape est déjà terminée'),
            backgroundColor: Colors.orange,
          ),
        );
        Navigator.of(context).pop();
        return;
      }

      if (!_isPreviousStepCompleted()) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(
            content: Text('L\'étape précédente n\'est pas terminée. Impossible d\'accéder à cette étape.'),
            backgroundColor: Colors.red,
          ),
        );
        Navigator.of(context).pop();
        return;
      }

      // Charger les équipements après le premier frame pour éviter setState pendant build
      _loadEquipmentAndContainers();
    });
  }

  /// Vérifie si l'étape actuelle est déjà complétée
  bool _isCurrentStepCompleted() {
    switch (_currentStep) {
      case PreparationStep.preparation:
        final status = _currentEvent.preparationStatus ?? PreparationStatus.notStarted;
        return status == PreparationStatus.completed || status == PreparationStatus.completedWithMissing;
      case PreparationStep.loadingOutbound:
        final status = _currentEvent.loadingStatus ?? LoadingStatus.notStarted;
        return status == LoadingStatus.completed || status == LoadingStatus.completedWithMissing;
      case PreparationStep.unloadingReturn:
        final status = _currentEvent.unloadingStatus ?? UnloadingStatus.notStarted;
        return status == UnloadingStatus.completed || status == UnloadingStatus.completedWithMissing;
      case PreparationStep.return_:
        final status = _currentEvent.returnStatus ?? ReturnStatus.notStarted;
        return status == ReturnStatus.completed || status == ReturnStatus.completedWithMissing;
    }
  }

  /// Vérifie si l'étape précédente est bien complétée
  bool _isPreviousStepCompleted() {
    switch (_currentStep) {
      case PreparationStep.preparation:
        return true; // Première étape, toujours OK
      case PreparationStep.loadingOutbound:
        final prep = _currentEvent.preparationStatus ?? PreparationStatus.notStarted;
        return prep == PreparationStatus.completed || prep == PreparationStatus.completedWithMissing;
      case PreparationStep.unloadingReturn:
        final loading = _currentEvent.loadingStatus ?? LoadingStatus.notStarted;
        return loading == LoadingStatus.completed || loading == LoadingStatus.completedWithMissing;
      case PreparationStep.return_:
        final unloading = _currentEvent.unloadingStatus ?? UnloadingStatus.notStarted;
        return unloading == UnloadingStatus.completed || unloading == UnloadingStatus.completedWithMissing;
    }
  }

  @override
  void dispose() {
    _animationController.dispose();
    _manualCodeController.dispose();
    _manualCodeFocusNode.dispose();
    SmartTextToSpeechService.stop();
    super.dispose();
  }

  Future<void> _loadEquipmentAndContainers() async {
    setState(() => _isLoading = true);

    try {
      // 🔧 FIX: Utiliser getEventWithDetails pour charger toutes les données d'un coup
      DebugLog.info('[EventPreparationPage] Loading event with details: ${_currentEvent.id}');

      final result = await _dataService.getEventWithDetails(_currentEvent.id);
      final equipmentsMap = result['equipments'] as Map<String, dynamic>;
      final containersMap = result['containers'] as Map<String, dynamic>;

      DebugLog.info('[EventPreparationPage] Loaded ${equipmentsMap.length} equipments and ${containersMap.length} containers with details');

      // Remplir les caches
      _equipmentCache.clear();
      _containerCache.clear();

      // Remplir le cache d'équipements
      equipmentsMap.forEach((id, data) {
        try {
          final equipment = EquipmentModel.fromMap(data as Map<String, dynamic>, id);
          _equipmentCache[id] = equipment;
        } catch (e) {
          DebugLog.error('[EventPreparationPage] Error parsing equipment $id', e);
        }
      });

      // Remplir le cache de containers
      containersMap.forEach((id, data) {
        try {
          final container = ContainerModel.fromMap(data as Map<String, dynamic>, id);
          _containerCache[id] = container;
        } catch (e) {
          DebugLog.error('[EventPreparationPage] Error parsing container $id', e);
        }
      });

      // Initialiser les états de validation et quantités pour chaque équipement assigné
      for (var eq in _currentEvent.assignedEquipment) {
        final equipmentItem = _equipmentCache[eq.equipmentId];

        // S'assurer que l'équipement est dans le cache (même si inconnu)
        if (equipmentItem == null) {
          _equipmentCache[eq.equipmentId] = EquipmentModel(
            id: eq.equipmentId,
            name: 'Équipement inconnu',
            category: EquipmentCategory.other,
            status: EquipmentStatus.available,
            maintenanceIds: [],
            createdAt: DateTime.now(),
            updatedAt: DateTime.now(),
          );
        }

        // Initialiser l'état local de validation depuis l'événement
        switch (_currentStep) {
          case PreparationStep.preparation:
            _localValidationState[eq.equipmentId] = eq.isPrepared;
            break;
          case PreparationStep.loadingOutbound:
            _localValidationState[eq.equipmentId] = eq.isLoaded;
            break;
          case PreparationStep.unloadingReturn:
            _localValidationState[eq.equipmentId] = eq.isUnloaded;
            break;
          case PreparationStep.return_:
            _localValidationState[eq.equipmentId] = eq.isReturned;
            break;
        }

        _quantitiesAtPreparation[eq.equipmentId] = eq.quantityAtPreparation ?? eq.quantity;
        _quantitiesAtLoading[eq.equipmentId] = eq.quantityAtLoading ?? eq.quantityAtPreparation ?? eq.quantity;
        _quantitiesAtUnloading[eq.equipmentId] = eq.quantityAtUnloading ?? eq.quantityAtLoading ?? eq.quantityAtPreparation ?? eq.quantity;
        _quantitiesAtReturn[eq.equipmentId] = eq.quantityAtReturn ?? eq.quantityAtUnloading ?? eq.quantityAtLoading ?? eq.quantityAtPreparation ?? eq.quantity;

        if ((_currentStep == PreparationStep.return_ ||
             _currentStep == PreparationStep.unloadingReturn) &&
            (equipmentItem?.hasQuantity ?? false)) {
          _returnedQuantities[eq.equipmentId] = eq.quantityAtReturn ?? eq.quantityAtUnloading ?? eq.quantityAtLoading ?? eq.quantityAtPreparation ?? eq.quantity;
        }
      }

      // S'assurer que les containers assignés sont dans le cache (même si inconnus)
      for (var containerId in _currentEvent.assignedContainers) {
        if (!_containerCache.containsKey(containerId)) {
          _containerCache[containerId] = ContainerModel(
            id: containerId,
            name: 'Conteneur inconnu',
            type: ContainerType.flightCase,
            status: EquipmentStatus.available,
            equipmentIds: [],
            updatedAt: DateTime.now(),
            createdAt: DateTime.now(),
          );
        }
      }
    } catch (e) {
      DebugLog.error('[EventPreparationPage] Error', e);
    } finally {
      setState(() => _isLoading = false);
    }
  }

  /// Basculer l'état de validation d'un équipement (état local uniquement)
  Future<void> _toggleEquipmentValidation(String equipmentId) async {
    final currentState = _localValidationState[equipmentId] ?? false;

    // Si on veut valider (passer de false à true) et que c'était manquant avant
    if (!currentState && _wasMissingAtPreviousStep(equipmentId)) {
      final confirmed = await _confirmValidationIfWasMissingBefore(equipmentId);
      if (!confirmed) {
        return; // Annulation, ne rien faire
      }
    }

    setState(() {
      _localValidationState[equipmentId] = !currentState;
    });
  }

  /// Marquer TOUT comme validé et enregistrer (bouton "Tout confirmer")
  Future<void> _validateAllAndConfirm() async {
    // Marquer tout comme validé localement
    setState(() {
      for (var eq in _currentEvent.assignedEquipment) {
        _localValidationState[eq.equipmentId] = true;
      }
    });

    // Puis enregistrer
    await _confirmCurrentState();
  }

  /// Enregistrer l'état actuel TEL QUEL (cochés = validés, non cochés = manquants)
  Future<void> _confirmCurrentState() async {
    setState(() => _isValidating = true);

    try {
      // Déterminer les manquants = équipements NON validés
      final Map<String, bool> missingAtThisStep = {};
      for (var eq in _currentEvent.assignedEquipment) {
        final isValidated = _localValidationState[eq.equipmentId] ?? false;
        missingAtThisStep[eq.equipmentId] = !isValidated; // Manquant si pas validé
      }

      // Préparer la liste des équipements avec leur nouvel état
      final updatedEquipment = _currentEvent.assignedEquipment.map((eq) {
        final isValidated = _localValidationState[eq.equipmentId] ?? false;
        final isMissing = missingAtThisStep[eq.equipmentId] ?? false;

        // Récupérer les quantités selon l'étape
        final qtyAtPrep = _quantitiesAtPreparation[eq.equipmentId];
        final qtyAtLoad = _quantitiesAtLoading[eq.equipmentId];
        final qtyAtUnload = _quantitiesAtUnloading[eq.equipmentId];
        final qtyAtRet = _quantitiesAtReturn[eq.equipmentId];

        switch (_currentStep) {
          case PreparationStep.preparation:
            if (_loadSimultaneously) {
              return eq.copyWith(
                isPrepared: isValidated,
                isLoaded: isValidated,
                isMissingAtPreparation: isMissing,
                isMissingAtLoading: isMissing, // Propager
                quantityAtPreparation: qtyAtPrep,
                quantityAtLoading: qtyAtPrep, // Même quantité
              );
            }
            return eq.copyWith(
              isPrepared: isValidated,
              isMissingAtPreparation: isMissing,
              quantityAtPreparation: qtyAtPrep,
            );

          case PreparationStep.loadingOutbound:
            return eq.copyWith(
              isLoaded: isValidated,
              isMissingAtLoading: isMissing,
              quantityAtLoading: qtyAtLoad,
            );

          case PreparationStep.unloadingReturn:
            if (_loadSimultaneously) {
              return eq.copyWith(
                isUnloaded: isValidated,
                isReturned: isValidated,
                isMissingAtUnloading: isMissing,
                isMissingAtReturn: isMissing, // Propager
                quantityAtUnloading: qtyAtUnload,
                quantityAtReturn: qtyAtRet ?? qtyAtUnload,
              );
            }
            return eq.copyWith(
              isUnloaded: isValidated,
              isMissingAtUnloading: isMissing,
              quantityAtUnloading: qtyAtUnload,
            );

          case PreparationStep.return_:
            return eq.copyWith(
              isReturned: isValidated,
              isMissingAtReturn: isMissing,
              quantityAtReturn: qtyAtRet,
            );
        }
      }).toList();

      // Mettre à jour Firestore selon l'étape
      final updateData = <String, dynamic>{
        'assignedEquipment': updatedEquipment.map((e) => e.toMap()).toList(),
      };

      // Ajouter les statuts selon l'étape et la checkbox
      String validationType = 'CHECK';
      switch (_currentStep) {
        case PreparationStep.preparation:
          updateData['preparationStatus'] = preparationStatusToString(PreparationStatus.completed);
          validationType = 'CHECK_OUT';
          if (_loadSimultaneously) {
            updateData['loadingStatus'] = loadingStatusToString(LoadingStatus.completed);
            validationType = 'LOADING';
          }
          break;

        case PreparationStep.loadingOutbound:
          updateData['loadingStatus'] = loadingStatusToString(LoadingStatus.completed);
          validationType = 'LOADING';
          break;

        case PreparationStep.unloadingReturn:
          updateData['unloadingStatus'] = unloadingStatusToString(UnloadingStatus.completed);
          validationType = 'UNLOADING';
          if (_loadSimultaneously) {
            updateData['returnStatus'] = returnStatusToString(ReturnStatus.completed);
            validationType = 'CHECK_IN';
          }
          break;

        case PreparationStep.return_:
          updateData['returnStatus'] = returnStatusToString(ReturnStatus.completed);
          validationType = 'CHECK_IN';
          break;
      }

      // Sauvegarder dans Firestore via l'API
      await _dataService.updateEventEquipment(
        eventId: _currentEvent.id,
        assignedEquipment: updatedEquipment.map((e) => e.toMap()).toList(),
        preparationStatus: updateData['preparationStatus'],
        loadingStatus: updateData['loadingStatus'],
        unloadingStatus: updateData['unloadingStatus'],
        returnStatus: updateData['returnStatus'],
      );

      // Mettre à jour les statuts des équipements si nécessaire (uniquement pour la préparation, le retour étant géré par le trigger Firestore Cloud Function)
      if (_currentStep == PreparationStep.preparation) {
        await _updateEquipmentStatuses(updatedEquipment);
      }

      // NOUVEAU: Appeler la Cloud Function pour traiter la validation
      // et créer les alertes automatiquement
      try {
        DebugLog.info('[EventPreparationPage] Appel processEquipmentValidation');

        final equipmentList = updatedEquipment.map((eq) {
          final equipment = _equipmentCache[eq.equipmentId];
          return {
            'equipmentId': eq.equipmentId,
            'name': equipment?.name ?? 'Équipement inconnu',
            'status': _determineEquipmentStatus(eq),
            'quantity': _getQuantityForStep(eq),
            'expectedQuantity': eq.quantity,
            'isMissingAtPreparation': eq.isMissingAtPreparation,
            'isMissingAtReturn': eq.isMissingAtReturn,
          };
        }).toList();

        final result = await FirebaseFunctions.instanceFor(region: 'europe-west9')
            .httpsCallable('processEquipmentValidation')
            .call({
          'eventId': _currentEvent.id,
          'equipmentList': equipmentList,
          'validationType': validationType,
        });

        final alertsCreated = result.data['alertsCreated'] ?? 0;
        if (alertsCreated > 0) {
          DebugLog.info('[EventPreparationPage] $alertsCreated alertes créées automatiquement');
        }
      } catch (e) {
        DebugLog.error('[EventPreparationPage] Erreur appel processEquipmentValidation', e);
        // Ne pas bloquer la validation si les alertes échouent
      }

      // Recharger l'événement depuis le provider
      final eventProvider = context.read<EventProvider>();

      // Recharger uniquement cet événement depuis l'API pour obtenir les dernières données
      try {
        final result = await _dataService.getEventWithDetails(_currentEvent.id);
        final eventData = result['event'] as Map<String, dynamic>;
        final updatedEvent = EventModel.fromMap(eventData, eventData['id'] as String);

        // Mettre à jour dans le cache
        await eventProvider.updateEvent(updatedEvent);
      } catch (e) {
        DebugLog.error('[EventPreparationPage] Erreur lors du rechargement de l\'événement', e);
      }

      setState(() => _showSuccessAnimation = true);
      _animationController.forward();

      await Future.delayed(const Duration(milliseconds: 500));

      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text(_getSuccessMessage()),
            backgroundColor: Colors.green,
          ),
        );

        await Future.delayed(const Duration(seconds: 2));
        Navigator.of(context).pop(true);
      }
    } catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('Erreur : $e'),
            backgroundColor: Colors.red,
          ),
        );
      }
    } finally {
      if (mounted) setState(() => _isValidating = false);
    }
  }

  Future<void> _updateEquipmentStatuses(List<EventEquipment> equipment) async {
    final List<String> failedUpdates = [];

    for (var eq in equipment) {
      try {
        final equipmentData = _equipmentCache[eq.equipmentId];
        if (equipmentData == null) continue;

        // Déterminer le nouveau statut
        EquipmentStatus newStatus;
        if (eq.isReturned) {
          // Note : Le retour est géré par le trigger Firestore Cloud Function en tâche de fond.
          // On évite les conflits d'écritures client/serveur et les double-restaurations de stock.
          continue;
        } else if (eq.isPrepared || eq.isLoaded) {
          newStatus = EquipmentStatus.inUse;
        } else {
          continue; // Pas de changement
        }

        // Ne mettre à jour que les équipements non quantifiables
        if (!equipmentData.hasQuantity) {
          await _dataService.updateEquipmentStatusOnly(
            equipmentId: eq.equipmentId,
            status: equipmentStatusToString(newStatus),
          );
        }
      } catch (e) {
        DebugLog.error('[EventPreparationPage] Échec de la mise à jour du statut pour l\'équipement ${eq.equipmentId}', e);
        failedUpdates.add(eq.equipmentId);
      }
    }

    if (failedUpdates.isNotEmpty && mounted) {
      final names = failedUpdates.map((id) => _equipmentCache[id]?.name ?? id).join(', ');
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text('Attention : Échec de mise à jour du statut en base pour : $names. Le matériel a tout de même été validé pour l\'événement.'),
          backgroundColor: Colors.orange,
          duration: const Duration(seconds: 6),
        ),
      );
    }
  }

  String _getSuccessMessage() {
    switch (_currentStep) {
      case PreparationStep.preparation:
        return _loadSimultaneously
            ? 'Préparation dépôt et chargement aller validés !'
            : 'Préparation dépôt validée !';
      case PreparationStep.loadingOutbound:
        return 'Chargement aller validé !';
      case PreparationStep.unloadingReturn:
        return _loadSimultaneously
            ? 'Chargement retour et retour dépôt validés !'
            : 'Chargement retour validé !';
      case PreparationStep.return_:
        return 'Retour dépôt validé !';
    }
  }

  String _getStepTitle() {
    switch (_currentStep) {
      case PreparationStep.preparation:
        return 'Préparation dépôt';
      case PreparationStep.loadingOutbound:
        return 'Chargement aller';
      case PreparationStep.unloadingReturn:
        return 'Chargement retour';
      case PreparationStep.return_:
        return 'Retour dépôt';
    }
  }

  String _getValidateAllButtonText() {
    if (_loadSimultaneously) {
      return _currentStep == PreparationStep.preparation
          ? 'Tout confirmer comme préparé et chargé'
          : 'Tout confirmer comme déchargé et retourné';
    }

    switch (_currentStep) {
      case PreparationStep.preparation:
        return 'Tout confirmer comme préparé';
      case PreparationStep.loadingOutbound:
        return 'Tout confirmer comme chargé';
      case PreparationStep.unloadingReturn:
        return 'Tout confirmer comme déchargé';
      case PreparationStep.return_:
        return 'Tout confirmer comme retourné';
    }
  }

  bool _isStepCompleted() {
    return _currentEvent.assignedEquipment.every((eq) {
      return _localValidationState[eq.equipmentId] ?? false;
    });
  }

  double _getProgress() {
    if (_currentEvent.assignedEquipment.isEmpty) return 0;
    return _getValidatedCount() / _currentEvent.assignedEquipment.length;
  }

  int _getValidatedCount() {
    return _currentEvent.assignedEquipment.where((eq) {
      return _localValidationState[eq.equipmentId] ?? false;
    }).length;
  }

  ChecklistStep _getChecklistStep() {
    switch (_currentStep) {
      case PreparationStep.preparation:
        return ChecklistStep.preparation;
      case PreparationStep.loadingOutbound:
        return ChecklistStep.loading;
      case PreparationStep.unloadingReturn:
        return ChecklistStep.unloading;
      case PreparationStep.return_:
        return ChecklistStep.return_;
    }
  }

  // ========================================================================
  // 🆕 NOUVELLES MÉTHODES POUR LE SCAN QR ET LA SAISIE MANUELLE
  // ========================================================================

  /// Ouvrir le scanner QR en mode multi-scan
  Future<void> _openQRScanner() async {
    await showDialog(
      context: context,
      builder: (context) => QRCodeScannerDialog(
        multiScanMode: true,
        onCodeScanned: _handleScannedCode,
      ),
    );
  }

  /// Traiter un code (scanné ou saisi manuellement)
  Future<void> _handleScannedCode(String code) async {
    final result = await _qrCodeService.processCode(
      code: code.trim(),
      event: _currentEvent,
      step: _currentStep,
      equipmentCache: _equipmentCache,
      containerCache: _containerCache,
      validationState: _localValidationState,
      currentQuantities: _getCurrentQuantitiesMap(),
    );

    if (result.success) {
      // ✅ Succès : mettre à jour l'état
      setState(() {
        if (result.updatedValidationState != null) {
          _localValidationState.addAll(result.updatedValidationState!);
        }
        if (result.updatedQuantities != null) {
          _updateQuantitiesMap(result.updatedQuantities!);
        }
      });

      // 🔊 Jouer le feedback sonore et haptique
      await AudioFeedbackService.playFullFeedback(isSuccess: true);

      // Feedback visuel
      _showSuccessFeedback(result.message ?? 'Code traité avec succès');

      // 🗣️ Annoncer le prochain item après un court délai
      await Future.delayed(const Duration(milliseconds: 500));
      await _announceNextItem();

    } else if (result.codeNotFoundInEvent) {
      // 🔍 Code non trouvé dans l'événement → proposer de l'ajouter
      // 🔊 Son d'erreur
      await AudioFeedbackService.playFullFeedback(isSuccess: false);

      await _handleCodeNotFoundInEvent(code.trim());

    } else {
      // ❌ Erreur (ex: quantité déjà atteinte, déjà coché)
      await AudioFeedbackService.playFullFeedback(isSuccess: false);
      _showErrorFeedback(result.message ?? 'Erreur lors du traitement');
    }
  }

  /// Gérer un code non trouvé dans l'événement
  Future<void> _handleCodeNotFoundInEvent(String code) async {
    // Afficher le dialog de confirmation
    final shouldSearch = await showDialog<bool>(
      context: context,
      builder: (context) => CodeNotFoundDialog(scannedCode: code),
    );

    if (shouldSearch != true) return;

    // Afficher le dialog de chargement
    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (context) => const AddEquipmentToEventDialog(
        state: AddEquipmentState.loading,
      ),
    );

    try {
      // Identifier le type selon le préfixe
      final isContainer = code.startsWith('BOX_');

      if (isContainer) {
        await _addContainerToEvent(code);
      } else {
        await _addEquipmentToEvent(code);
      }

      // 🔊 Bip de succès
      await AudioFeedbackService.playFullFeedback(isSuccess: true);

    } catch (e) {
      DebugLog.error('[EventPreparationPage] Error adding item to event', e);

      // Fermer le dialog de chargement et afficher l'erreur
      if (mounted) Navigator.of(context).pop();

      await showDialog(
        context: context,
        builder: (context) => AddEquipmentToEventDialog(
          state: AddEquipmentState.error,
          errorMessage: e.toString(),
        ),
      );

      // 🔊 Bip d'erreur
      await AudioFeedbackService.playFullFeedback(isSuccess: false);
    }
  }

  /// Ajouter un équipement à l'événement
  Future<void> _addEquipmentToEvent(String equipmentId) async {
    // Rechercher l'équipement dans la base de données
    final equipmentProvider = context.read<EquipmentProvider>();
    await equipmentProvider.ensureLoaded();

    // Chercher d'abord dans le cache
    EquipmentModel? equipment = equipmentProvider.allEquipment
        .cast<EquipmentModel?>()
        .firstWhere(
          (eq) => eq?.id == equipmentId,
          orElse: () => null,
        );

    // Si pas dans le cache, charger depuis Firestore
    if (equipment == null) {
      final equipmentService = EquipmentService();
      equipment = await equipmentService.getEquipmentById(equipmentId);
    }

    if (equipment == null) {
      throw Exception('Équipement non trouvé dans la base de données');
    }

    // Ajouter l'équipement à l'événement
    final newEventEquipment = EventEquipment(
      equipmentId: equipmentId,
      quantity: 1,
    );

    final updatedEquipment = List<EventEquipment>.from(_currentEvent.assignedEquipment)
      ..add(newEventEquipment);

    await _dataService.updateEvent(_currentEvent.id, {
      'assignedEquipment': updatedEquipment.map((e) => e.toMap()).toList(),
    });

    // Mettre à jour l'état local
    setState(() {
      _currentEvent = _currentEvent.copyWith(
        assignedEquipment: updatedEquipment,
      );
      _equipmentCache[equipmentId] = equipment!;
      _localValidationState[equipmentId] = false;
    });

    // Fermer le dialog de chargement et afficher le succès
    if (mounted) Navigator.of(context).pop();

    await showDialog(
      context: context,
      builder: (context) => AddEquipmentToEventDialog(
        state: AddEquipmentState.success,
        itemName: equipment!.name,
      ),
    );
  }

  /// Ajouter un container à l'événement
  Future<void> _addContainerToEvent(String containerId) async {
    // Rechercher le container dans la base de données
    final containerProvider = context.read<ContainerProvider>();
    await containerProvider.ensureLoaded();

    final container = await containerProvider.getContainerById(containerId);

    if (container == null) {
      throw Exception('Container non trouvé dans la base de données');
    }

    // Ajouter le container à l'événement
    final updatedContainers = List<String>.from(_currentEvent.assignedContainers)
      ..add(containerId);

    await _dataService.updateEvent(_currentEvent.id, {
      'assignedContainers': updatedContainers,
    });

    // Mettre à jour l'état local
    setState(() {
      _currentEvent = _currentEvent.copyWith(
        assignedContainers: updatedContainers,
      );
      _containerCache[containerId] = container;
    });

    // Fermer le dialog de chargement et afficher le succès
    if (mounted) Navigator.of(context).pop();

    await showDialog(
      context: context,
      builder: (context) => AddEquipmentToEventDialog(
        state: AddEquipmentState.success,
        itemName: 'Container ${container.name}',
      ),
    );
  }

  /// Traiter la saisie manuelle d'un code
  Future<void> _handleManualCodeEntry(String code) async {
    if (code.trim().isEmpty) return;

    // Ajouter le code à la file d'attente
    _scanQueue.add(code.trim());

    // Effacer le champ immédiatement pour permettre le prochain scan
    _manualCodeController.clear();

    // Maintenir le focus sur le champ pour permettre une saisie continue
    _manualCodeFocusNode.requestFocus();

    // Démarrer le traitement de la file si pas déjà en cours
    if (!_isProcessingQueue) {
      _processQueue();
    }
  }

  /// Traite la file d'attente des scans un par un
  Future<void> _processQueue() async {
    if (_isProcessingQueue) return;

    _isProcessingQueue = true;

    while (_scanQueue.isNotEmpty) {
      final code = _scanQueue.removeAt(0);
      await _handleScannedCode(code);
    }

    _isProcessingQueue = false;
  }

  /// Obtenir les quantités actuelles selon l'étape
  Map<String, int> _getCurrentQuantitiesMap() {
    switch (_currentStep) {
      case PreparationStep.preparation:
        return _quantitiesAtPreparation;
      case PreparationStep.loadingOutbound:
        return _quantitiesAtLoading;
      case PreparationStep.unloadingReturn:
        return _quantitiesAtUnloading;
      case PreparationStep.return_:
        return _quantitiesAtReturn;
    }
  }

  /// Mettre à jour les quantités selon l'étape
  void _updateQuantitiesMap(Map<String, int> quantities) {
    switch (_currentStep) {
      case PreparationStep.preparation:
        _quantitiesAtPreparation.addAll(quantities);
        break;
      case PreparationStep.loadingOutbound:
        _quantitiesAtLoading.addAll(quantities);
        break;
      case PreparationStep.unloadingReturn:
        _quantitiesAtUnloading.addAll(quantities);
        break;
      case PreparationStep.return_:
        _quantitiesAtReturn.addAll(quantities);
        break;
    }

    // Mettre à jour `_currentEvent.assignedEquipment` pour que l'UI se reconstruise avec les bonnes valeurs
    final updatedList = _currentEvent.assignedEquipment.map((eq) {
      final qty = quantities[eq.equipmentId];
      if (qty != null) {
        switch (_currentStep) {
          case PreparationStep.preparation:
            return eq.copyWith(quantityAtPreparation: qty);
          case PreparationStep.loadingOutbound:
            return eq.copyWith(quantityAtLoading: qty);
          case PreparationStep.unloadingReturn:
            return eq.copyWith(quantityAtUnloading: qty);
          case PreparationStep.return_:
            return eq.copyWith(quantityAtReturn: qty);
        }
      }
      return eq;
    }).toList();

    _currentEvent = _currentEvent.copyWith(assignedEquipment: updatedList);
  }


  /// Afficher un message de succès
  void _showSuccessFeedback(String message) {
    if (!mounted) return;
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Row(
          children: [
            const Icon(Icons.check_circle, color: Colors.white),
            const SizedBox(width: 12),
            Expanded(child: Text(message)),
          ],
        ),
        backgroundColor: Colors.green,
        duration: const Duration(seconds: 2),
      ),
    );
  }

  /// Afficher un message d'erreur
  void _showErrorFeedback(String message) {
    if (!mounted) return;
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Row(
          children: [
            const Icon(Icons.error, color: Colors.white),
            const SizedBox(width: 12),
            Expanded(child: Text(message)),
          ],
        ),
        backgroundColor: Colors.orange,
        duration: const Duration(seconds: 3),
      ),
    );
  }

  // ========================================================================
  // FIN DES NOUVELLES MÉTHODES
  // ========================================================================

  Future<void> _confirm() async {
    // Vérifier s'il y a des équipements manquants (non cochés localement)
    final missingEquipmentIds = _currentEvent.assignedEquipment
        .where((eq) => !(_localValidationState[eq.equipmentId] ?? false))
        .map((eq) => eq.equipmentId)
        .toList();

    if (missingEquipmentIds.isEmpty) {
      // Tout est validé, confirmer directement
      await _confirmCurrentState();
    } else {
      // Afficher le dialog des manquants
      final missingEquipmentModels = missingEquipmentIds
          .map((id) => _equipmentCache[id])
          .whereType<EquipmentModel>()
          .toList();

      final missingEventEquipment = _currentEvent.assignedEquipment
          .where((eq) => missingEquipmentIds.contains(eq.equipmentId))
          .toList();

      final action = await showDialog<String>(
        context: context,
        builder: (context) => MissingEquipmentDialog(
          missingEquipment: missingEquipmentModels,
          eventEquipment: missingEventEquipment,
          isReturnMode: _currentStep == PreparationStep.return_ ||
                        _currentStep == PreparationStep.unloadingReturn,
        ),
      );

      if (action == 'confirm_anyway') {
        // Confirmer malgré les manquants (enregistrer l'état actuel TEL QUEL)
        await _confirmCurrentState();
      } else if (action == 'mark_as_validated') {
        // Marquer les manquants comme validés localement
        for (var equipmentId in missingEquipmentIds) {
          _localValidationState[equipmentId] = true;
        }
        setState(() {});
        // Puis confirmer
        await _confirmCurrentState();
      }
      // Si 'return_to_list', ne rien faire
    }
  }

  /// Valider tous les enfants d'un container
  void _validateAllContainerChildren(String containerId) {
    final container = _containerCache[containerId];
    if (container == null) return;

    setState(() {
      for (final equipmentId in container.equipmentIds) {
        if (_equipmentCache.containsKey(equipmentId)) {
          _localValidationState[equipmentId] = true;
        }
      }
    });
  }

  /// Mettre à jour la quantité d'un équipement à l'étape actuelle
  void _updateEquipmentQuantity(String equipmentId, int newQuantity) {
    setState(() {
      _updateQuantitiesMap({equipmentId: newQuantity});
    });
  }

  /// Vérifier si un équipement était manquant à l'étape précédente
  bool _wasMissingAtPreviousStep(String equipmentId) {
    final eq = _currentEvent.assignedEquipment.firstWhere(
      (e) => e.equipmentId == equipmentId,
      orElse: () => EventEquipment(equipmentId: equipmentId),
    );

    switch (_currentStep) {
      case PreparationStep.preparation:
        return false; // Pas d'étape avant
      case PreparationStep.loadingOutbound:
        return eq.isMissingAtPreparation;
      case PreparationStep.unloadingReturn:
        return eq.isMissingAtLoading;
      case PreparationStep.return_:
        return eq.isMissingAtUnloading;
    }
  }

  /// Afficher pop-up de confirmation si l'équipement était manquant avant
  Future<bool> _confirmValidationIfWasMissingBefore(String equipmentId) async {
    if (!_wasMissingAtPreviousStep(equipmentId)) {
      return true; // Pas de problème, continuer
    }

    final equipment = _equipmentCache[equipmentId];
    final result = await showDialog<bool>(
      context: context,
      builder: (context) => AlertDialog(
        title: const Row(
          children: [
            Icon(Icons.warning_amber, color: Colors.orange),
            SizedBox(width: 8),
            Text('Confirmation'),
          ],
        ),
        content: Text(
          'L\'équipement "${equipment?.name ?? equipmentId}" était manquant à l\'étape précédente.\n\n'
          'Êtes-vous sûr de le marquer comme présent maintenant ?',
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(false),
            child: const Text('Annuler'),
          ),
          ElevatedButton(
            onPressed: () => Navigator.of(context).pop(true),
            style: ElevatedButton.styleFrom(
              backgroundColor: Colors.orange,
            ),
            child: const Text('Confirmer'),
          ),
        ],
      ),
    );

    return result ?? false;
  }

  /// Détermine le statut d'un équipement selon l'étape actuelle
  String _determineEquipmentStatus(EventEquipment eq) {
    if (_isNotTakenToEventAtReturn(eq)) {
      return 'NOT_TAKEN';
    }

    // Vérifier d'abord si l'équipement est perdu (LOST)
    if (_shouldMarkAsLost(eq)) {
      return 'LOST';
    }

    // Vérifier si manquant à l'étape actuelle
    if (_isMissingAtCurrentStep(eq)) {
      return 'MISSING';
    }

    // Vérifier les quantités
    final currentQty = _getQuantityForStep(eq);
    if (currentQty != null && currentQty < eq.quantity) {
      return 'QUANTITY_MISMATCH';
    }

    return 'AVAILABLE';
  }

  /// Vérifie si un équipement doit être marqué comme LOST
  bool _shouldMarkAsLost(EventEquipment eq) {
    return EventPreparationService.shouldMarkEquipmentAsLost(
      isReturnValidationStep: _isReturnValidationStep,
      isMissingAtReturn: eq.isMissingAtReturn,
      isLoaded: eq.isLoaded,
      isMissingAtLoading: eq.isMissingAtLoading,
      quantityAtLoading: eq.quantityAtLoading,
    );
  }

  bool _isNotTakenToEventAtReturn(EventEquipment eq) {
    if (!_isReturnValidationStep) {
      return false;
    }

    return EventPreparationService.isEquipmentNotTakenToEvent(
      isMissingAtReturn: eq.isMissingAtReturn,
      isLoaded: eq.isLoaded,
      isMissingAtLoading: eq.isMissingAtLoading,
      quantityAtLoading: eq.quantityAtLoading,
    );
  }

  bool get _isReturnValidationStep {
    return _currentStep == PreparationStep.return_ ||
        (_currentStep == PreparationStep.unloadingReturn && _loadSimultaneously);
  }

  /// Vérifie si un équipement est manquant à l'étape actuelle
  bool _isMissingAtCurrentStep(EventEquipment eq) {
    switch (_currentStep) {
      case PreparationStep.preparation:
        return eq.isMissingAtPreparation;
      case PreparationStep.loadingOutbound:
        return eq.isMissingAtLoading;
      case PreparationStep.unloadingReturn:
        return eq.isMissingAtUnloading;
      case PreparationStep.return_:
        return eq.isMissingAtReturn;
    }
  }

  /// Récupère la quantité pour l'étape actuelle
  int? _getQuantityForStep(EventEquipment eq) {
    switch (_currentStep) {
      case PreparationStep.preparation:
        return eq.quantityAtPreparation;
      case PreparationStep.loadingOutbound:
        return eq.quantityAtLoading;
      case PreparationStep.unloadingReturn:
        return eq.quantityAtUnloading;
      case PreparationStep.return_:
        return eq.quantityAtReturn;
    }
  }

  /// Trouve le prochain item non validé à scanner
  String? _findNextItemToScan() {
    // Parcourir les items dans l'ordre et trouver le premier non validé

    // 1. Parcourir les containers et leurs équipements
    for (final containerId in _currentEvent.assignedContainers) {
      final container = _containerCache[containerId];
      if (container == null) continue;

      // Vérifier si le container a des équipements non validés
      bool hasUnvalidatedChild = false;
      for (final equipmentId in container.equipmentIds) {

        if (_currentEvent.assignedEquipment.any((e) => e.equipmentId == equipmentId)) {
          final isValidated = _localValidationState[equipmentId] ?? false;
          if (!isValidated) {
            hasUnvalidatedChild = true;
            break;
          }
        }
      }

      // Si le container a des items non validés, retourner le nom du container
      if (hasUnvalidatedChild) {
        return container.name;
      }
    }

    // 2. Parcourir les équipements standalone (pas dans un container)
    final Set<String> equipmentIdsInContainers = {};
    for (final containerId in _currentEvent.assignedContainers) {
      final container = _containerCache[containerId];
      if (container != null) {
        equipmentIdsInContainers.addAll(container.equipmentIds);
      }
    }

    for (final eventEquipment in _currentEvent.assignedEquipment) {
      if (equipmentIdsInContainers.contains(eventEquipment.equipmentId)) {
        continue;
      }

      final isValidated = _localValidationState[eventEquipment.equipmentId] ?? false;
      if (!isValidated) {
        final equipment = _equipmentCache[eventEquipment.equipmentId];
        return equipment?.name ?? 'Équipement ${eventEquipment.equipmentId}';
      }
    }

    return null; // Tout est validé
  }

  /// Annonce vocalement le prochain item à scanner
  Future<void> _announceNextItem() async {
    final nextItem = _findNextItemToScan();
    if (nextItem != null) {
      await SmartTextToSpeechService.speak('Prochain item: $nextItem');
    } else {
      await SmartTextToSpeechService.speak('Tous les items sont validés');
    }
  }

  @override
  Widget build(BuildContext context) {
    final allValidated = _isStepCompleted();
    final stepTitle = _getStepTitle();

    return Scaffold(
      appBar: AppBar(
        title: Text(stepTitle),
        backgroundColor: AppColors.bleuFonce,
        actions: const [
          AudioDiagnosticButton(),
        ],
      ),
      body: Stack(
        children: [
          _isLoading
              ? const Center(child: CircularProgressIndicator())
              : Column(
                  children: [
                    Container(
                      padding: const EdgeInsets.all(16),
                      color: Colors.grey.shade100,
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.stretch,
                        children: [
                          // Nom de l'événement et barre de progression sur la même ligne
                          Row(
                            children: [
                              Expanded(
                                child: Text(
                                  _currentEvent.name,
                                  style: const TextStyle(
                                    fontSize: 18,
                                    fontWeight: FontWeight.bold,
                                  ),
                                  maxLines: 2,
                                  overflow: TextOverflow.ellipsis,
                                ),
                              ),
                              const SizedBox(width: 12),
                              Expanded(
                                child: Row(
                                  children: [
                                    Expanded(
                                      child: LinearProgressIndicator(
                                        value: _getProgress(),
                                        backgroundColor: Colors.grey.shade300,
                                        valueColor: AlwaysStoppedAnimation<Color>(
                                          allValidated ? Colors.green : AppColors.bleuFonce,
                                        ),
                                      ),
                                    ),
                                    const SizedBox(width: 8),
                                    Text(
                                      '${_getValidatedCount()}/${_currentEvent.assignedEquipment.length}',
                                      style: const TextStyle(
                                        fontWeight: FontWeight.bold,
                                        fontSize: 14,
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                            ],
                          ),
                          const SizedBox(height: 12),

                          // Checkbox "charger en même temps" (uniquement pour préparation ou chargement retour)
                          if (_currentStep == PreparationStep.preparation ||
                              _currentStep == PreparationStep.unloadingReturn)
                            CheckboxListTile(
                              value: _loadSimultaneously,
                              onChanged: (value) {
                                setState(() {
                                  _loadSimultaneously = value ?? false;
                                });
                              },
                              title: Text(
                                _currentStep == PreparationStep.preparation
                                    ? 'Charger en même temps (chargement aller)'
                                    : 'Confirmer le retour en même temps (retour dépôt)',
                                style: const TextStyle(
                                  fontSize: 14,
                                  fontWeight: FontWeight.w500,
                                ),
                              ),
                              dense: true,
                              contentPadding: EdgeInsets.zero,
                            ),

                          // Champ de saisie manuelle avec bouton scanner
                          const SizedBox(height: 12),
                          Row(
                            children: [
                              Expanded(
                                child: TextField(
                                  controller: _manualCodeController,
                                  focusNode: _manualCodeFocusNode,
                                  decoration: InputDecoration(
                                    labelText: 'Saisie manuelle d\'un code',
                                    hintText: 'ID d\'équipement ou container',
                                    prefixIcon: const Icon(Icons.keyboard, color: AppColors.bleuFonce),
                                    suffixIcon: _manualCodeController.text.isNotEmpty
                                        ? IconButton(
                                            icon: const Icon(Icons.clear),
                                            onPressed: () {
                                              _manualCodeController.clear();
                                              setState(() {});
                                            },
                                          )
                                        : null,
                                    border: OutlineInputBorder(
                                      borderRadius: BorderRadius.circular(8),
                                    ),
                                    focusedBorder: OutlineInputBorder(
                                      borderRadius: BorderRadius.circular(8),
                                      borderSide: const BorderSide(color: AppColors.bleuFonce, width: 2),
                                    ),
                                    contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
                                  ),
                                  onSubmitted: _handleManualCodeEntry,
                                  onChanged: (value) => setState(() {}),
                                  textInputAction: TextInputAction.done,
                                ),
                              ),
                              const SizedBox(width: 8),
                              // IconButton pour scanner QR Code
                              Container(
                                decoration: BoxDecoration(
                                  color: Colors.blue[700],
                                  borderRadius: BorderRadius.circular(8),
                                ),
                                child: IconButton(
                                  onPressed: _openQRScanner,
                                  icon: const Icon(Icons.qr_code_scanner, color: Colors.white),
                                  iconSize: 28,
                                  tooltip: 'Scanner QR Code',
                                ),
                              ),
                            ],
                          ),

                          const SizedBox(height: 8),
                          ElevatedButton.icon(
                            onPressed: allValidated ? null : _validateAllAndConfirm,
                            icon: const Icon(Icons.check_circle_outline),
                            label: Text(
                              allValidated
                                  ? 'Tout est validé !'
                                  : _getValidateAllButtonText(),
                            ),
                            style: ElevatedButton.styleFrom(
                              backgroundColor: allValidated ? Colors.green : AppColors.bleuFonce,
                              padding: const EdgeInsets.symmetric(vertical: 12),
                            ),
                          ),
                        ],
                      ),
                    ),
                    Expanded(
                      child: LayoutBuilder(
                        builder: (context, constraints) {
                          // Afficher 2 colonnes si la largeur le permet (> 600px)
                          final useColumns = constraints.maxWidth > 600;
                          final items = _buildChecklistItems();

                          if (useColumns && items.length > 1) {
                            // Diviser en 2 colonnes
                            final mid = (items.length / 2).ceil();
                            final leftItems = items.sublist(0, mid);
                            final rightItems = items.sublist(mid);

                            return Row(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                Expanded(
                                  child: ListView(
                                    padding: const EdgeInsets.all(16),
                                    children: leftItems,
                                  ),
                                ),
                                const VerticalDivider(width: 1),
                                Expanded(
                                  child: ListView(
                                    padding: const EdgeInsets.all(16),
                                    children: rightItems,
                                  ),
                                ),
                              ],
                            );
                          } else {
                            // Une seule colonne
                            return ListView(
                              padding: const EdgeInsets.all(16),
                              children: items,
                            );
                          }
                        },
                      ),
                    ),
                  ],
                ),
          if (_showSuccessAnimation)
            Center(
              child: ScaleTransition(
                scale: _animationController,
                child: Container(
                  padding: const EdgeInsets.all(32),
                  decoration: const BoxDecoration(
                    color: Colors.green,
                    shape: BoxShape.circle,
                  ),
                  child: const Icon(
                    Icons.check,
                    size: 64,
                    color: Colors.white,
                  ),
                ),
              ),
            ),
        ],
      ),
      bottomNavigationBar: Container(
        padding: const EdgeInsets.all(16),
        decoration: BoxDecoration(
          color: Colors.white,
          boxShadow: [
            BoxShadow(
              color: Colors.black.withValues(alpha: 0.1),
              blurRadius: 4,
              offset: const Offset(0, -2),
            ),
          ],
        ),
        child: ElevatedButton(
          onPressed: _isValidating ? null : _confirm,
          style: ElevatedButton.styleFrom(
            backgroundColor: allValidated ? Colors.green : AppColors.rouge,
            padding: const EdgeInsets.symmetric(vertical: 16),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(8),
            ),
          ),
          child: _isValidating
              ? const SizedBox(
                  height: 20,
                  width: 20,
                  child: CircularProgressIndicator(
                    strokeWidth: 2,
                    valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
                  ),
                )
              : Text(
                  'Confirmer ${_getStepTitle().toLowerCase()}',
                  style: const TextStyle(
                    fontSize: 18,
                    fontWeight: FontWeight.bold,
                  ),
                ),
        ),
      ),
    );
  }

  /// Construit la liste des items de checklist en groupant par containers
  List<Widget> _buildChecklistItems() {
    final List<Widget> items = [];

    // Set pour tracker les équipements déjà affichés dans un container
    final Set<String> equipmentIdsInContainers = {};

    // Map des EventEquipment par ID pour accès rapide
    final Map<String, EventEquipment> eventEquipmentsMap = {
      for (var eq in _currentEvent.assignedEquipment) eq.equipmentId: eq,
    };

    // 1. Afficher les containers avec leurs enfants
    for (final containerId in _currentEvent.assignedContainers) {
      final container = _containerCache[containerId];
      if (container == null) continue;

      // Récupérer les équipements enfants de ce container
      final List<EquipmentModel> childEquipments = [];
      for (final equipmentId in container.equipmentIds) {
        final equipment = _equipmentCache[equipmentId];
        if (equipment != null && eventEquipmentsMap.containsKey(equipmentId)) {
          childEquipments.add(equipment);
          equipmentIdsInContainers.add(equipmentId);
        }
      }

      if (childEquipments.isEmpty) continue;

      // Vérifier si tous les enfants sont validés
      final allChildrenValidated = childEquipments.every(
        (eq) => _localValidationState[eq.id] ?? false,
      );

      // Map des états de validation des enfants
      final Map<String, bool> childValidationStates = {
        for (var eq in childEquipments) eq.id: _localValidationState[eq.id] ?? false,
      };

      // Map des enfants manquants à l'étape précédente
      final Map<String, bool> wasMissingBeforeMap = {
        for (var eq in childEquipments) eq.id: _wasMissingAtPreviousStep(eq.id),
      };

      items.add(
        ContainerChecklistItem(
          container: container,
          childEquipments: childEquipments,
          eventEquipmentsMap: eventEquipmentsMap,
          step: _getChecklistStep(),
          isValidated: allChildrenValidated,
          childValidationStates: childValidationStates,
          onToggleContainer: () => _validateAllContainerChildren(containerId),
          onToggleChild: (equipmentId) => _toggleEquipmentValidation(equipmentId),
          onQuantityChanged: (equipmentId, qty) => _updateEquipmentQuantity(equipmentId, qty),
          wasMissingBeforeMap: wasMissingBeforeMap,
        ),
      );
    }

    // 2. Afficher les équipements standalone (pas dans un container)
    for (final eventEquipment in _currentEvent.assignedEquipment) {
      // Skip si déjà affiché dans un container
      if (equipmentIdsInContainers.contains(eventEquipment.equipmentId)) {
        continue;
      }

      final equipment = _equipmentCache[eventEquipment.equipmentId];
      if (equipment == null) continue;

      items.add(
        EquipmentChecklistItem(
          equipment: equipment,
          eventEquipment: eventEquipment,
          step: _getChecklistStep(),
          isValidated: _localValidationState[equipment.id] ?? false,
          onToggle: () => _toggleEquipmentValidation(equipment.id),
          onQuantityChanged: (qty) => _updateEquipmentQuantity(equipment.id, qty),
          isChild: false, // Équipement standalone (pas indenté)
          wasMissingBefore: _wasMissingAtPreviousStep(equipment.id),
        ),
      );
    }

    return items;
  }
}

