import 'dart:async';
import 'package:flutter/material.dart';
import 'package:geosector_app/core/theme/app_theme.dart';
import 'package:flutter/foundation.dart' show kIsWeb, debugPrint;
import 'package:hive_flutter/hive_flutter.dart';
import 'package:geosector_app/core/data/models/passage_model.dart';
import 'package:geosector_app/core/repositories/passage_repository.dart';
import 'package:geosector_app/core/repositories/user_repository.dart';
import 'package:geosector_app/core/repositories/operation_repository.dart';
import 'package:geosector_app/core/repositories/amicale_repository.dart';
import 'package:geosector_app/core/services/current_user_service.dart';
import 'package:geosector_app/core/services/current_amicale_service.dart';
import 'package:geosector_app/core/services/stripe_tap_to_pay_service.dart';
import 'package:geosector_app/core/services/stripe_connect_service.dart';
import 'package:geosector_app/core/services/api_service.dart';
import 'package:geosector_app/core/utils/api_exception.dart';
import 'package:geosector_app/core/constants/app_keys.dart';
import 'package:geosector_app/core/services/location_service.dart';
import 'package:geosector_app/presentation/widgets/custom_text_field.dart';
import 'package:geosector_app/presentation/widgets/form_section.dart';
import 'package:geosector_app/presentation/widgets/result_dialog.dart';
import 'package:geosector_app/presentation/widgets/loading_spin_overlay.dart';
import 'package:geosector_app/presentation/widgets/payment_method_selection_dialog.dart';

class PassageFormDialog extends StatefulWidget {
  final PassageModel? passage;
  final String title;
  final bool readOnly;
  final PassageRepository passageRepository;
  final UserRepository userRepository;
  final OperationRepository operationRepository;
  final AmicaleRepository amicaleRepository;
  final VoidCallback? onSuccess;

  const PassageFormDialog({
    super.key,
    this.passage,
    required this.title,
    this.readOnly = false,
    required this.passageRepository,
    required this.userRepository,
    required this.operationRepository,
    required this.amicaleRepository,
    this.onSuccess,
  });

  @override
  State<PassageFormDialog> createState() => _PassageFormDialogState();
}

class _PassageFormDialogState extends State<PassageFormDialog> {
  final _formKey = GlobalKey<FormState>();
  bool _isSubmitting = false;

  // Sélection du type de passage
  int? _selectedPassageType;
  bool _showForm = false;

  // Controllers
  late final TextEditingController _numeroController;
  late final TextEditingController _rueBisController;
  late final TextEditingController _rueController;
  late final TextEditingController _villeController;
  late final TextEditingController _nameController;
  late final TextEditingController _emailController;
  late final TextEditingController _phoneController;
  late final TextEditingController _montantController;
  late final TextEditingController _apptController;
  late final TextEditingController _niveauController;
  late final TextEditingController _residenceController;
  late final TextEditingController _remarqueController;
  late final TextEditingController _dateController;
  late final TextEditingController _timeController;

  // Form values
  int _fkHabitat = 1; // Par défaut Maison
  int _fkTypeReglement = 4; // Par défaut Non renseigné
  DateTime _passedAt = DateTime.now(); // Date et heure de passage

  // Variable pour Tap to Pay
  String? _stripePaymentIntentId;

  // État d'expansion des sections
  bool _isAddressSectionExpanded = true;
  bool _isDateTimeSectionExpanded = false; // Toujours fermée par défaut

  // Boîte Hive pour mémoriser la dernière adresse
  late Box _settingsBox;

  // Helpers de validation
  String? _validateNumero(String? value) {
    debugPrint('🔍 [VALIDATOR] _validateNumero appelé avec: "$value"');
    if (value == null || value.trim().isEmpty) {
      debugPrint('❌ [VALIDATOR] Numéro vide -> retourne erreur');
      return 'Le numéro est obligatoire';
    }
    final numero = int.tryParse(value.trim());
    if (numero == null || numero <= 0) {
      debugPrint('❌ [VALIDATOR] Numéro invalide: $value -> retourne erreur');
      return 'Numéro invalide';
    }
    debugPrint('✅ [VALIDATOR] Numéro valide: $numero');
    return null;
  }

  String? _validateRue(String? value) {
    if (value == null || value.trim().isEmpty) {
      return 'La rue est obligatoire';
    }
    if (value.trim().length < 3) {
      return 'La rue doit contenir au moins 3 caractères';
    }
    return null;
  }

  String? _validateVille(String? value) {
    if (value == null || value.trim().isEmpty) {
      return 'La ville est obligatoire';
    }
    return null;
  }

  String? _validateNomOccupant(String? value) {
    // Le nom est obligatoire uniquement si un email est renseigné
    final emailValue = _emailController.text.trim();
    if (emailValue.isNotEmpty) {
      if (value == null || value.trim().isEmpty) {
        return 'Le nom est obligatoire si un email est renseigné';
      }
      if (value.trim().length < 2) {
        return 'Le nom doit contenir au moins 2 caractères';
      }
    }
    return null;
  }

  String? _validateEmail(String? value) {
    if (value == null || value.trim().isEmpty) {
      return null; // Email optionnel
    }
    const emailRegex = r'^[^@]+@[^@]+\.[^@]+$';
    if (!RegExp(emailRegex).hasMatch(value.trim())) {
      return 'Format email invalide';
    }
    return null;
  }

  String? _validateMontant(String? value) {
    if (_selectedPassageType == 1 || _selectedPassageType == 5) {
      if (value == null || value.trim().isEmpty) {
        return 'Le montant est obligatoire pour ce type';
      }
      final montant = double.tryParse(value.replaceAll(',', '.'));
      if (montant == null) {
        return 'Montant invalide';
      }
      if (montant <= 0) {
        return 'Le montant doit être supérieur à 0';
      }
    }
    return null;
  }

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

    try {
      debugPrint('=== DEBUT PassageFormDialog.initState ===');

      // Accéder à la settingsBox (déjà ouverte dans l'app)
      _settingsBox = Hive.box(AppKeys.settingsBoxName);

      // Initialize controllers with passage data if available
      final passage = widget.passage;
      debugPrint('Passage reçu: ${passage != null}');

      if (passage != null) {
        debugPrint('Passage ID: ${passage.id}');
        debugPrint('Passage fkType: ${passage.fkType}');
        debugPrint('Passage numero: ${passage.numero}');
        debugPrint('Passage rueBis: ${passage.rueBis}');
        debugPrint('Passage rue: ${passage.rue}');
        debugPrint('Passage ville: ${passage.ville}');
        debugPrint('Passage name: ${passage.name}');
        debugPrint('Passage email: ${passage.email}');
        debugPrint('Passage phone: ${passage.phone}');
        debugPrint('Passage montant: ${passage.montant}');
        debugPrint('Passage remarque: ${passage.remarque}');
        debugPrint('Passage fkHabitat: ${passage.fkHabitat}');
        debugPrint('Passage fkTypeReglement: ${passage.fkTypeReglement}');
      }

      _selectedPassageType = passage?.fkType;
      _showForm = false; // Toujours commencer par la sélection de type
      _fkHabitat = passage?.fkHabitat ?? 1;
      _fkTypeReglement = passage?.fkTypeReglement ?? 4;

      // Section Adresse : ouverte si nouveau passage, fermée si modification
      _isAddressSectionExpanded = passage == null;

      debugPrint('Initialisation des controllers...');

      // S'assurer que toutes les valeurs null deviennent des chaînes vides
      String numero = passage?.numero.toString() ?? '';
      String rueBis = passage?.rueBis.toString() ?? '';
      String rue = passage?.rue.toString() ?? '';
      String ville = passage?.ville.toString() ?? '';
      final String name = passage?.name.toString() ?? '';
      final String email = passage?.email.toString() ?? '';
      final String phone = passage?.phone.toString() ?? '';
      // Pour le montant, afficher vide si c'est 0.00
      final String montantRaw = passage?.montant.toString() ?? '0.00';
      final String montant =
          (montantRaw == '0.00' || montantRaw == '0' || montantRaw == '0.0')
              ? ''
              : montantRaw;
      String appt = passage?.appt.toString() ?? '';
      String niveau = passage?.niveau.toString() ?? '';
      String residence = passage?.residence.toString() ?? '';
      final String remarque = passage?.remarque.toString() ?? '';

      // Si nouveau passage, charger les valeurs mémorisées de la dernière adresse
      if (passage == null) {
        debugPrint('Nouveau passage: chargement des valeurs mémorisées...');
        numero = _settingsBox.get('lastPassageNumero', defaultValue: '') as String;
        rueBis = _settingsBox.get('lastPassageRueBis', defaultValue: '') as String;
        rue = _settingsBox.get('lastPassageRue', defaultValue: '') as String;
        ville = _settingsBox.get('lastPassageVille', defaultValue: '') as String;
        residence = _settingsBox.get('lastPassageResidence', defaultValue: '') as String;
        _fkHabitat = _settingsBox.get('lastPassageFkHabitat', defaultValue: 1) as int;
        appt = _settingsBox.get('lastPassageAppt', defaultValue: '') as String;
        niveau = _settingsBox.get('lastPassageNiveau', defaultValue: '') as String;

        debugPrint('Valeurs chargées: numero="$numero", rue="$rue", ville="$ville"');
      }

      // Initialiser la date de passage
      _passedAt = passage?.passedAt ?? DateTime.now();
      final String dateFormatted =
          '${_passedAt.day.toString().padLeft(2, '0')}/${_passedAt.month.toString().padLeft(2, '0')}/${_passedAt.year}';
      final String timeFormatted =
          '${_passedAt.hour.toString().padLeft(2, '0')}:${_passedAt.minute.toString().padLeft(2, '0')}';

      debugPrint('Valeurs pour controllers:');
      debugPrint('  numero: "$numero"');
      debugPrint('  rueBis: "$rueBis"');
      debugPrint('  rue: "$rue"');
      debugPrint('  ville: "$ville"');
      debugPrint('  name: "$name"');
      debugPrint('  email: "$email"');
      debugPrint('  phone: "$phone"');
      debugPrint('  montant: "$montant"');
      debugPrint('  remarque: "$remarque"');
      debugPrint('  passedAt: "$_passedAt"');
      debugPrint('  dateFormatted: "$dateFormatted"');
      debugPrint('  timeFormatted: "$timeFormatted"');

      _numeroController = TextEditingController(text: numero);
      _rueBisController = TextEditingController(text: rueBis);
      _rueController = TextEditingController(text: rue);
      _villeController = TextEditingController(text: ville);
      _nameController = TextEditingController(text: name);
      _emailController = TextEditingController(text: email);
      _phoneController = TextEditingController(text: phone);
      _montantController = TextEditingController(text: montant);
      _apptController = TextEditingController(text: appt);
      _niveauController = TextEditingController(text: niveau);
      _residenceController = TextEditingController(text: residence);
      _remarqueController = TextEditingController(text: remarque);
      _dateController = TextEditingController(text: dateFormatted);
      _timeController = TextEditingController(text: timeFormatted);

      // Ajouter un listener sur le champ email pour mettre à jour la validation du nom
      _emailController.addListener(() {
        // Force la revalidation du formulaire quand l'email change
        if (mounted) {
          setState(() {
            // Cela va déclencher un rebuild et mettre à jour l'indicateur isRequired
          });
        }
      });

      debugPrint('=== FIN PassageFormDialog.initState ===');
    } catch (e, stackTrace) {
      debugPrint('=== ERREUR PassageFormDialog.initState ===');
      debugPrint('Erreur: $e');
      debugPrint('StackTrace: $stackTrace');
      rethrow;
    }
  }

  @override
  void dispose() {
    _numeroController.dispose();
    _rueBisController.dispose();
    _rueController.dispose();
    _villeController.dispose();
    _nameController.dispose();
    _emailController.dispose();
    _phoneController.dispose();
    _montantController.dispose();
    _apptController.dispose();
    _niveauController.dispose();
    _residenceController.dispose();
    _remarqueController.dispose();
    _dateController.dispose();
    _timeController.dispose();
    super.dispose();
  }

  void _selectPassageType(int typeId) {
    setState(() {
      _selectedPassageType = typeId;
      _showForm = true;

      // Réinitialiser montant et type de règlement selon le type de passage
      if (typeId == 1 || typeId == 5) {
        // Pour "Effectué" (1) ou "Lot" (5), laisser le choix à l'utilisateur
        // Ne pas forcer un type de règlement spécifique
      } else {
        // Pour tous les autres types, réinitialiser
        _montantController.text = '';
        _fkTypeReglement = 4; // Non renseigné
      }

      // Toujours mettre à jour la date et l'heure à maintenant lors de la sélection du type
      _passedAt = DateTime.now();
      _dateController.text =
          '${_passedAt.day.toString().padLeft(2, '0')}/${_passedAt.month.toString().padLeft(2, '0')}/${_passedAt.year}';
      _timeController.text =
          '${_passedAt.hour.toString().padLeft(2, '0')}:${_passedAt.minute.toString().padLeft(2, '0')}';
    });
  }

  void _handleSubmit() async {
    debugPrint('🔵 [SUBMIT] Début _handleSubmit');

    if (_isSubmitting) {
      debugPrint('⚠️ [SUBMIT] Déjà en cours de soumission, abandon');
      return;
    }

    debugPrint('🔵 [SUBMIT] Vérification de l\'état du formulaire');
    debugPrint('🔵 [SUBMIT] _formKey: $_formKey');
    debugPrint('🔵 [SUBMIT] _formKey.currentState: ${_formKey.currentState}');

    // Validation avec protection contre le null
    if (_formKey.currentState == null) {
      debugPrint('❌ [SUBMIT] ERREUR: _formKey.currentState est null !');
      if (mounted) {
        await ResultDialog.show(
          context: context,
          success: false,
          message: "Erreur d'initialisation du formulaire",
        );
      }
      return;
    }

    debugPrint('🔵 [SUBMIT] Validation du formulaire...');
    final isValid = _formKey.currentState!.validate();
    debugPrint('🔵 [SUBMIT] Résultat validation: $isValid');

    if (!isValid) {
      debugPrint('⚠️ [SUBMIT] Validation échouée, abandon');

      // Afficher un dialog d'erreur clair à l'utilisateur
      if (mounted) {
        await ResultDialog.show(
          context: context,
          success: false,
          message: 'Veuillez vérifier tous les champs marqués comme obligatoires',
        );
      }
      return;
    }

    debugPrint('✅ [SUBMIT] Validation OK, appel _savePassage()');
    await _savePassage();
    debugPrint('🔵 [SUBMIT] Fin _handleSubmit');
  }

  Future<void> _savePassage() async {
    debugPrint('🟢 [SAVE] Début _savePassage');

    if (_isSubmitting) {
      debugPrint('⚠️ [SAVE] Déjà en cours de soumission, abandon');
      return;
    }

    debugPrint('🟢 [SAVE] Mise à jour état _isSubmitting = true');
    setState(() {
      _isSubmitting = true;
    });

    // Afficher l'overlay de chargement
    debugPrint('🟢 [SAVE] Affichage overlay de chargement');
    final overlay = LoadingSpinOverlayUtils.show(
      context: context,
      message: 'Enregistrement en cours...',
    );

    try {
      debugPrint('🟢 [SAVE] Récupération utilisateur actuel');
      final currentUser = widget.userRepository.getCurrentUser();
      debugPrint('🟢 [SAVE] currentUser: ${currentUser?.id} - ${currentUser?.name}');

      if (currentUser == null) {
        debugPrint('❌ [SAVE] ERREUR: Utilisateur non connecté');
        throw Exception("Utilisateur non connecté");
      }

      debugPrint('🟢 [SAVE] Récupération opération active');
      final currentOperation = widget.operationRepository.getCurrentOperation();
      debugPrint('🟢 [SAVE] currentOperation: ${currentOperation?.id} - ${currentOperation?.name}');

      if (currentOperation == null && widget.passage == null) {
        debugPrint('❌ [SAVE] ERREUR: Aucune opération active trouvée');
        throw Exception("Aucune opération active trouvée");
      }

      // Déterminer les valeurs de montant et type de règlement selon le type de passage
      debugPrint('🟢 [SAVE] Calcul des valeurs finales');
      debugPrint('🟢 [SAVE] _selectedPassageType: $_selectedPassageType');

      final String finalMontant =
          (_selectedPassageType == 1 || _selectedPassageType == 5)
              ? _montantController.text.trim().replaceAll(',', '.')
              : '0';
      debugPrint('🟢 [SAVE] finalMontant: $finalMontant');

      // Déterminer le type de règlement final selon le type de passage
      final int finalTypeReglement;
      if (_selectedPassageType == 1 || _selectedPassageType == 5) {
        // Pour les types 1 et 5, utiliser la valeur sélectionnée (qui a été validée)
        finalTypeReglement = _fkTypeReglement;
      } else {
        // Pour tous les autres types, forcer "Non renseigné"
        finalTypeReglement = 4;
      }
      debugPrint('🟢 [SAVE] finalTypeReglement: $finalTypeReglement');

      // Déterminer la valeur de nbPassages selon le type de passage
      final int finalNbPassages;
      if (widget.passage != null) {
        // Modification d'un passage existant
        if (_selectedPassageType == 2) {
          // Type 2 (À finaliser) : toujours incrémenter
          finalNbPassages = widget.passage!.nbPassages + 1;
        } else {
          // Autres types : mettre à 1 si actuellement 0, sinon conserver
          final currentNbPassages = widget.passage!.nbPassages;
          finalNbPassages = currentNbPassages == 0 ? 1 : currentNbPassages;
        }
      } else {
        // Nouveau passage : toujours 1
        finalNbPassages = 1;
      }
      debugPrint('🟢 [SAVE] finalNbPassages: $finalNbPassages');

      // Récupérer les coordonnées GPS pour un nouveau passage
      String finalGpsLat = '0.0';
      String finalGpsLng = '0.0';
      if (widget.passage == null) {
        // Nouveau passage : tenter de récupérer la position GPS actuelle
        debugPrint('🟢 [SAVE] Récupération de la position GPS...');
        try {
          final position = await LocationService.getCurrentPosition();
          if (position != null) {
            finalGpsLat = position.latitude.toString();
            finalGpsLng = position.longitude.toString();
            debugPrint('🟢 [SAVE] GPS récupéré: lat=$finalGpsLat, lng=$finalGpsLng');
          } else {
            debugPrint('🟢 [SAVE] GPS non disponible, utilisation de 0.0 (l\'API utilisera le géocodage)');
          }
        } catch (e) {
          debugPrint('⚠️ [SAVE] Erreur récupération GPS: $e - l\'API utilisera le géocodage');
        }
      } else {
        // Modification : conserver les coordonnées existantes
        finalGpsLat = widget.passage!.gpsLat;
        finalGpsLng = widget.passage!.gpsLng;
      }

      final passageData = widget.passage?.copyWith(
            fkType: _selectedPassageType!,
            numero: _numeroController.text.trim(),
            rueBis: _rueBisController.text.trim(),
            rue: _rueController.text.trim(),
            ville: _villeController.text.trim(),
            name: _nameController.text.trim(),
            email: _emailController.text.trim(),
            phone: _phoneController.text.trim(),
            montant: finalMontant,
            fkHabitat: _fkHabitat,
            appt: _apptController.text.trim(),
            niveau: _niveauController.text.trim(),
            residence: _residenceController.text.trim(),
            remarque: _remarqueController.text.trim(),
            fkTypeReglement: finalTypeReglement,
            nbPassages: finalNbPassages,
            passedAt: _passedAt,
            stripePaymentId: _stripePaymentIntentId,
            lastSyncedAt: DateTime.now(),
          ) ??
          PassageModel(
            id: 0, // Nouveau passage
            fkOperation: currentOperation!.id, // Opération active
            fkSector: 0, // Secteur par défaut (sera déterminé par l'API)
            fkUser: currentUser.id, // Utilisateur actuel
            fkType: _selectedPassageType!,
            fkAdresse: "0", // Adresse par défaut pour nouveau passage
            passedAt: _passedAt,
            numero: _numeroController.text.trim(),
            rue: _rueController.text.trim(),
            rueBis: _rueBisController.text.trim(),
            ville: _villeController.text.trim(),
            residence: _residenceController.text.trim(),
            fkHabitat: _fkHabitat,
            appt: _apptController.text.trim(),
            niveau: _niveauController.text.trim(),
            gpsLat: finalGpsLat, // GPS de l'utilisateur ou 0.0 si non disponible
            gpsLng: finalGpsLng, // GPS de l'utilisateur ou 0.0 si non disponible
            nomRecu: _nameController.text.trim(),
            remarque: _remarqueController.text.trim(),
            montant: finalMontant,
            fkTypeReglement: finalTypeReglement,
            emailErreur: '',
            nbPassages: finalNbPassages,
            name: _nameController.text.trim(),
            email: _emailController.text.trim(),
            phone: _phoneController.text.trim(),
            stripePaymentId: _stripePaymentIntentId,
            lastSyncedAt: DateTime.now(),
            isActive: true,
            isSynced: false,
          );

      // Sauvegarder le passage d'abord
      debugPrint('🟢 [SAVE] Préparation sauvegarde passage');
      PassageModel? savedPassage;
      if (widget.passage == null || widget.passage!.id == 0) {
        // Création d'un nouveau passage (passage null OU id=0)
        debugPrint('🟢 [SAVE] Création d\'un nouveau passage');
        savedPassage = await widget.passageRepository.createPassageWithReturn(passageData);
        debugPrint('🟢 [SAVE] Passage créé avec ID: ${savedPassage?.id}');

        if (savedPassage == null) {
          debugPrint('❌ [SAVE] ERREUR: savedPassage est null après création');
          throw Exception("Échec de la création du passage");
        }
      } else {
        // Mise à jour d'un passage existant
        debugPrint('🟢 [SAVE] Mise à jour passage existant ID: ${widget.passage!.id}');
        await widget.passageRepository.updatePassage(passageData);
        debugPrint('🟢 [SAVE] Mise à jour réussie');
        savedPassage = passageData;
      }

      // Garantir le type non-nullable après la vérification
      final confirmedPassage = savedPassage;
      debugPrint('✅ [SAVE] Passage sauvegardé avec succès ID: ${confirmedPassage.id}');

      // Mémoriser l'adresse pour la prochaine création de passage
      debugPrint('🟢 [SAVE] Mémorisation adresse');
      await _saveLastPassageAddress();

      // Propager la résidence aux autres passages de l'immeuble si nécessaire
      if (_fkHabitat == 2 && _residenceController.text.trim().isNotEmpty) {
        debugPrint('🟢 [SAVE] Propagation résidence à l\'immeuble');
        await _propagateResidenceToBuilding(confirmedPassage);
      }

      // Vérifier si paiement CB nécessaire APRÈS la sauvegarde
      if (finalTypeReglement == 3 &&
          (_selectedPassageType == 1 || _selectedPassageType == 5)) {
        final montant = double.tryParse(finalMontant.replaceAll(',', '.')) ?? 0;

        if (montant > 0 && mounted) {
          // Vérifier si l'amicale a Stripe activé
          final amicale = CurrentAmicaleService.instance.currentAmicale;
          final stripeEnabled = amicale?.chkStripe == true &&
                               amicale?.stripeId != null &&
                               amicale!.stripeId.isNotEmpty;

          if (stripeEnabled) {
            // Masquer le loading avant d'afficher le dialog de sélection
            LoadingSpinOverlayUtils.hideSpecific(overlay);

            // Afficher le dialog de sélection de méthode de paiement
            if (mounted) {
              final habitantName = _nameController.text.trim();
              await PaymentMethodSelectionDialog.show(
                context: context,
                passage: confirmedPassage,
                amount: montant,
                habitantName: habitantName.isNotEmpty ? habitantName : 'Client',
                stripeConnectService: StripeConnectService(
                  apiService: ApiService.instance,
                ),
                passageRepository: widget.passageRepository,
                onTapToPaySelected: () async {
                  // Lancer le flow Tap to Pay
                  final paymentSuccess = await _attemptTapToPayWithPassage(confirmedPassage, montant);

                  if (paymentSuccess) {
                    // Fermer le formulaire en cas de succès
                    if (mounted) {
                      Navigator.of(context, rootNavigator: false).pop();
                      widget.onSuccess?.call();
                    }
                  } else {
                    debugPrint('⚠️ Paiement Tap to Pay échoué - formulaire reste ouvert');
                    // Ne pas fermer le formulaire en cas d'échec
                    // L'utilisateur peut réessayer ou annuler
                  }
                },
                onQRCodeCompleted: () {
                  // Pour QR Code: fermer le formulaire après l'affichage du QR
                  if (mounted) {
                    Navigator.of(context, rootNavigator: false).pop();
                    widget.onSuccess?.call();
                  }
                },
              );

              // NOTE: Le formulaire n'est plus fermé systématiquement ici
              // Il est fermé dans onQRCodeCompleted pour QR Code
              // ou dans onTapToPaySelected en cas de succès Tap to Pay
            }
          } else {
            // Stripe non activé pour cette amicale
            LoadingSpinOverlayUtils.hideSpecific(overlay);

            if (mounted) {
              await ResultDialog.show(
                context: context,
                success: true,
                message: "Passage enregistré avec succès.\n\nℹ️ Note : Les paiements par carte ne sont pas activés pour votre amicale. Contactez l'administrateur pour activer Stripe.",
              );

              if (mounted) {
                Navigator.of(context, rootNavigator: false).pop();
                widget.onSuccess?.call();
              }
            }
          }
        }
      } else {
        // Pas de paiement CB, afficher le succès
        LoadingSpinOverlayUtils.hideSpecific(overlay);

        if (mounted) {
          await ResultDialog.show(
            context: context,
            success: true,
            message: widget.passage == null || widget.passage!.id == 0
                ? "Nouveau passage créé avec succès"
                : "Passage modifié avec succès",
          );

          if (mounted) {
            Navigator.of(context, rootNavigator: false).pop();
            widget.onSuccess?.call();
          }
        }
      }
    } catch (e, stackTrace) {
      // Masquer le loading
      debugPrint('❌ [SAVE] ERREUR CAPTURÉE');
      debugPrint('❌ [SAVE] Type erreur: ${e.runtimeType}');
      debugPrint('❌ [SAVE] Message erreur: $e');
      debugPrint('❌ [SAVE] Stack trace:\n$stackTrace');

      LoadingSpinOverlayUtils.hideSpecific(overlay);

      // Afficher l'erreur
      final errorMessage = ApiException.fromError(e).message;
      debugPrint('❌ [SAVE] Message d\'erreur formaté: $errorMessage');

      if (mounted) {
        await ResultDialog.show(
          context: context,
          success: false,
          message: errorMessage,
        );
      }
    } finally {
      debugPrint('🟢 [SAVE] Bloc finally - Nettoyage');
      if (mounted) {
        setState(() {
          _isSubmitting = false;
        });
        debugPrint('🟢 [SAVE] _isSubmitting = false');
      }
      debugPrint('🟢 [SAVE] Fin _savePassage');
    }
  }

  /// Mémoriser l'adresse du passage pour la prochaine création
  Future<void> _saveLastPassageAddress() async {
    try {
      debugPrint('🟡 [ADDRESS] Début mémorisation adresse');
      debugPrint('🟡 [ADDRESS] _settingsBox.isOpen: ${_settingsBox.isOpen}');

      await _settingsBox.put('lastPassageNumero', _numeroController.text.trim());
      await _settingsBox.put('lastPassageRueBis', _rueBisController.text.trim());
      await _settingsBox.put('lastPassageRue', _rueController.text.trim());
      await _settingsBox.put('lastPassageVille', _villeController.text.trim());
      await _settingsBox.put('lastPassageResidence', _residenceController.text.trim());
      await _settingsBox.put('lastPassageFkHabitat', _fkHabitat);
      await _settingsBox.put('lastPassageAppt', _apptController.text.trim());
      await _settingsBox.put('lastPassageNiveau', _niveauController.text.trim());

      debugPrint('✅ [ADDRESS] Adresse mémorisée avec succès');
    } catch (e, stackTrace) {
      debugPrint('❌ [ADDRESS] Erreur lors de la mémorisation: $e');
      debugPrint('❌ [ADDRESS] Stack trace:\n$stackTrace');
    }
  }

  /// Propager la résidence aux autres passages de l'immeuble (fkType=2, même adresse, résidence vide)
  Future<void> _propagateResidenceToBuilding(PassageModel savedPassage) async {
    try {
      debugPrint('🟡 [PROPAGATE] Début propagation résidence');

      final passagesBox = Hive.box<PassageModel>(AppKeys.passagesBoxName);
      debugPrint('🟡 [PROPAGATE] passagesBox.isOpen: ${passagesBox.isOpen}');
      debugPrint('🟡 [PROPAGATE] passagesBox.length: ${passagesBox.length}');

      final residence = _residenceController.text.trim();
      debugPrint('🟡 [PROPAGATE] résidence: "$residence"');

      // Clé d'adresse du passage sauvegardé
      final addressKey = '${savedPassage.numero}|${savedPassage.rueBis}|${savedPassage.rue}|${savedPassage.ville}';
      debugPrint('🟡 [PROPAGATE] addressKey: "$addressKey"');

      int updatedCount = 0;

      // Parcourir tous les passages
      for (int i = 0; i < passagesBox.length; i++) {
        final passage = passagesBox.getAt(i);
        if (passage != null) {
          // Vérifier les critères
          final passageAddressKey = '${passage.numero}|${passage.rueBis}|${passage.rue}|${passage.ville}';

          if (passage.id != savedPassage.id && // Pas le passage actuel
              passage.fkHabitat == 2 && // Appartement
              passageAddressKey == addressKey && // Même adresse
              passage.residence.trim().isEmpty) { // Résidence vide

            debugPrint('🟡 [PROPAGATE] Mise à jour passage ID: ${passage.id}');
            // Mettre à jour la résidence dans Hive
            final updatedPassage = passage.copyWith(residence: residence);
            await passagesBox.put(passage.key, updatedPassage);
            updatedCount++;
          }
        }
      }

      if (updatedCount > 0) {
        debugPrint('✅ [PROPAGATE] Résidence propagée à $updatedCount passage(s)');
      } else {
        debugPrint('✅ [PROPAGATE] Aucun passage à mettre à jour');
      }
    } catch (e, stackTrace) {
      debugPrint('❌ [PROPAGATE] Erreur lors de la propagation: $e');
      debugPrint('❌ [PROPAGATE] Stack trace:\n$stackTrace');
    }
  }

  Widget _buildPassageTypeSelection() {
    final theme = Theme.of(context);

    // Récupérer l'amicale de l'utilisateur pour vérifier chkLotActif
    final currentUser = CurrentUserService.instance.currentUser;
    bool showLotType = true; // Par défaut, on affiche le type Lot

    if (currentUser != null && currentUser.fkEntite != null) {
      final userAmicale = widget.amicaleRepository.getAmicaleById(currentUser.fkEntite!);
      if (userAmicale != null) {
        // Si chkLotActif = false (0), on ne doit pas afficher le type Lot (5)
        showLotType = userAmicale.chkLotActif;
        debugPrint('Amicale ${userAmicale.name}: chkLotActif = $showLotType');
      }
    }

    // Filtrer les types de passages en fonction de chkLotActif
    final filteredTypes = Map<int, Map<String, dynamic>>.from(AppKeys.typesPassages);
    if (!showLotType) {
      filteredTypes.remove(5); // Retirer le type "Lot" si chkLotActif = 0
      debugPrint('Type Lot (5) masqué car chkLotActif = false');
    }

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          'Type de passage',
          style: theme.textTheme.titleMedium?.copyWith(
            fontWeight: FontWeight.bold,
            color: theme.colorScheme.primary,
          ),
        ),
        const SizedBox(height: 16),
        GridView.builder(
          shrinkWrap: true,
          physics: const NeverScrollableScrollPhysics(),
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 2,
            childAspectRatio:
                MediaQuery.of(context).size.width < 600 ? 1.8 : 2.5,
            crossAxisSpacing: 12,
            mainAxisSpacing: 12,
          ),
          itemCount: filteredTypes.length,
          itemBuilder: (context, index) {
            try {
              final typeId = filteredTypes.keys.elementAt(index);
              final typeData = filteredTypes[typeId];

              if (typeData == null) {
                debugPrint('ERREUR: typeData null pour typeId: $typeId');
                return const SizedBox();
              }

              final isSelected = _selectedPassageType == typeId;

              return InkWell(
                onTap:
                    widget.readOnly ? null : () => _selectPassageType(typeId),
                borderRadius: BorderRadius.circular(12),
                child: Container(
                  padding: const EdgeInsets.all(16),
                  decoration: BoxDecoration(
                    color: Color(typeData['couleur2'] as int? ?? 0xFF000000)
                        .withOpacity(0.15),
                    border: Border.all(
                      color: Color(typeData['couleur2'] as int? ?? 0xFF000000),
                      width: isSelected ? 3 : 2,
                    ),
                    borderRadius: BorderRadius.circular(12),
                    boxShadow: isSelected
                        ? [
                            BoxShadow(
                              color: Color(typeData['couleur2'] as int? ??
                                      0xFF000000)
                                  .withOpacity(0.2),
                              blurRadius: 8,
                              offset: const Offset(0, 2),
                            )
                          ]
                        : null,
                  ),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Icon(
                        typeData['icon_data'] as IconData? ?? Icons.help,
                        color:
                            Color(typeData['couleur2'] as int? ?? 0xFF000000),
                        size: 36, // Icône plus grande
                      ),
                      const SizedBox(height: 8),
                      Text(
                        typeData['titre'] as String? ?? 'Type inconnu',
                        style: theme.textTheme.bodyMedium?.copyWith(
                          fontWeight:
                              isSelected ? FontWeight.bold : FontWeight.w600,
                          color: isSelected
                              ? Color(
                                  typeData['couleur2'] as int? ?? 0xFF000000)
                              : theme.colorScheme.onSurface,
                        ),
                        textAlign: TextAlign.center,
                        overflow: TextOverflow.ellipsis,
                        maxLines: 2,
                      ),
                    ],
                  ),
                ),
              );
            } catch (e) {
              debugPrint('ERREUR dans itemBuilder pour index $index: $e');
              return const SizedBox();
            }
          },
        ),
      ],
    );
  }

  Widget _buildPassageForm() {
    try {
      debugPrint('=== DEBUT _buildPassageForm ===');

      debugPrint('Building Form...');
      return Form(
        key: _formKey,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // Section Date et Heure (rétractable)
            Theme(
              data: Theme.of(context).copyWith(dividerColor: Colors.transparent),
              child: ExpansionTile(
                key: ValueKey(_isDateTimeSectionExpanded),
                initiallyExpanded: _isDateTimeSectionExpanded,
                onExpansionChanged: (expanded) {
                  setState(() {
                    _isDateTimeSectionExpanded = expanded;
                  });
                },
                leading: Icon(
                  Icons.schedule,
                  color: Theme.of(context).colorScheme.primary,
                ),
                title: _isDateTimeSectionExpanded
                    ? Text(
                        'Date et Heure de passage',
                        style: TextStyle(
                          fontSize: 16,
                          fontWeight: FontWeight.bold,
                          color: Theme.of(context).colorScheme.primary,
                        ),
                      )
                    : Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(
                            'Date et Heure de passage',
                            style: TextStyle(
                              fontSize: 16,
                              fontWeight: FontWeight.bold,
                              color: Theme.of(context).colorScheme.primary,
                            ),
                          ),
                          const SizedBox(height: 4),
                          Text(
                            '${_dateController.text} à ${_timeController.text}',
                            style: TextStyle(
                              fontSize: 14,
                              color: Colors.grey[600],
                            ),
                          ),
                        ],
                      ),
                children: [
                  Padding(
                    padding: const EdgeInsets.fromLTRB(16, 16, 16, 16),
                    child: Column(
                      children: [
                        // Layout responsive : 1 ligne desktop, 2 lignes mobile
                        _isMobile(context)
                            ? Column(
                                children: [
                                  CustomTextField(
                                    controller: _dateController,
                                    label: "Date",
                                    isRequired: true,
                                    readOnly: true,
                                    showLabel: false,
                                    hintText: "DD/MM/YYYY",
                                    suffixIcon: const Icon(Icons.calendar_today),
                                    onTap: widget.readOnly ? null : _selectDate,
                                  ),
                                  const SizedBox(height: 16),
                                  CustomTextField(
                                    controller: _timeController,
                                    label: "Heure",
                                    isRequired: true,
                                    readOnly: true,
                                    showLabel: false,
                                    hintText: "HH:MM",
                                    suffixIcon: const Icon(Icons.access_time),
                                    onTap: widget.readOnly ? null : _selectTime,
                                  ),
                                ],
                              )
                            : Row(
                                children: [
                                  Expanded(
                                    child: CustomTextField(
                                      controller: _dateController,
                                      label: "Date",
                                      isRequired: true,
                                      readOnly: true,
                                      showLabel: false,
                                      hintText: "DD/MM/YYYY",
                                      suffixIcon: const Icon(Icons.calendar_today),
                                      onTap: widget.readOnly ? null : _selectDate,
                                    ),
                                  ),
                                  const SizedBox(width: 12),
                                  Expanded(
                                    child: CustomTextField(
                                      controller: _timeController,
                                      label: "Heure",
                                      isRequired: true,
                                      readOnly: true,
                                      showLabel: false,
                                      hintText: "HH:MM",
                                      suffixIcon: const Icon(Icons.access_time),
                                      onTap: widget.readOnly ? null : _selectTime,
                                    ),
                                  ),
                                ],
                              ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
            const SizedBox(height: 24),

            // Section Adresse (rétractable)
            Theme(
              data: Theme.of(context).copyWith(dividerColor: Colors.transparent),
              child: ExpansionTile(
                key: ValueKey(_isAddressSectionExpanded),
                initiallyExpanded: _isAddressSectionExpanded,
                onExpansionChanged: (expanded) {
                  setState(() {
                    _isAddressSectionExpanded = expanded;
                  });
                },
                leading: Icon(
                  Icons.location_on,
                  color: Theme.of(context).colorScheme.primary,
                ),
                title: _isAddressSectionExpanded
                    ? Text(
                        'Adresse',
                        style: TextStyle(
                          fontSize: 16,
                          fontWeight: FontWeight.bold,
                          color: Theme.of(context).colorScheme.primary,
                        ),
                      )
                    : Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(
                            'Adresse',
                            style: TextStyle(
                              fontSize: 16,
                              fontWeight: FontWeight.bold,
                              color: Theme.of(context).colorScheme.primary,
                            ),
                          ),
                          const SizedBox(height: 4),
                          Text(
                            '${_numeroController.text} ${_rueBisController.text} ${_rueController.text}, ${_villeController.text}'.trim().replaceAll(RegExp(r'\s+'), ' '),
                            style: TextStyle(
                              fontSize: 14,
                              color: Colors.grey[600],
                            ),
                            maxLines: 1,
                            overflow: TextOverflow.ellipsis,
                          ),
                        ],
                      ),
                children: [
                  Padding(
                    padding: const EdgeInsets.fromLTRB(16, 16, 16, 16),
                    child: Column(
                      children: [
                        Row(
                          children: [
                            Expanded(
                              flex: 1,
                              child: CustomTextField(
                                controller: _numeroController,
                                label: "Numéro",
                                isRequired: true,
                                showLabel: false,
                                textAlign: TextAlign.right,
                                keyboardType: TextInputType.number,
                                readOnly: widget.readOnly,
                                validator: _validateNumero,
                              ),
                            ),
                            const SizedBox(width: 12),
                            Expanded(
                              flex: 1,
                              child: CustomTextField(
                                controller: _rueBisController,
                                label: "Bis, Ter...",
                                showLabel: false,
                                readOnly: widget.readOnly,
                              ),
                            ),
                          ],
                        ),
                        const SizedBox(height: 16),
                        CustomTextField(
                          controller: _rueController,
                          label: "Rue",
                          isRequired: true,
                          showLabel: false,
                          readOnly: widget.readOnly,
                          validator: _validateRue,
                        ),
                        const SizedBox(height: 16),
                        CustomTextField(
                          controller: _villeController,
                          label: "Ville",
                          isRequired: true,
                          showLabel: false,
                          readOnly: widget.readOnly,
                          validator: _validateVille,
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
            const SizedBox(height: 24),

            // Section Habitat
            FormSection(
              title: 'Habitat',
              icon: Icons.home,
              children: [
                // Boutons radio pour le type d'habitat
                Row(
                  children: [
                    Expanded(
                      // TODO: Migrer vers RadioGroup quand disponible (Flutter 4.0+)
                      child: RadioListTile<int>(
                        title: const Text('Maison'),
                        value: 1,
                        groupValue: _fkHabitat, // ignore: deprecated_member_use
                        onChanged: widget.readOnly // ignore: deprecated_member_use
                            ? null
                            : (value) {
                                setState(() {
                                  _fkHabitat = value!;
                                });
                              },
                        contentPadding: EdgeInsets.zero,
                      ),
                    ),
                    Expanded(
                      child: RadioListTile<int>(
                        title: const Text('Appart'),
                        value: 2,
                        groupValue: _fkHabitat, // ignore: deprecated_member_use
                        onChanged: widget.readOnly // ignore: deprecated_member_use
                            ? null
                            : (value) {
                                setState(() {
                                  _fkHabitat = value!;
                                });
                              },
                        contentPadding: EdgeInsets.zero,
                      ),
                    ),
                  ],
                ),

                // Champs spécifiques aux appartements
                if (_fkHabitat == 2) ...[
                  const SizedBox(height: 16),
                  Row(
                    children: [
                      Expanded(
                        flex: 1,
                        child: TextField(
                          controller: _niveauController,
                          decoration: const InputDecoration(
                            labelText: "Niveau",
                            border: OutlineInputBorder(),
                          ),
                          maxLength: 5,
                          readOnly: widget.readOnly,
                        ),
                      ),
                      const SizedBox(width: 12),
                      Expanded(
                        flex: 1,
                        child: TextField(
                          controller: _apptController,
                          decoration: const InputDecoration(
                            labelText: "Appt",
                            border: OutlineInputBorder(),
                          ),
                          maxLength: 5,
                          readOnly: widget.readOnly,
                        ),
                      ),
                    ],
                  ),
                  const SizedBox(height: 16),
                  TextField(
                    controller: _residenceController,
                    decoration: const InputDecoration(
                      labelText: "Résidence",
                      border: OutlineInputBorder(),
                    ),
                    maxLength: 50,
                    readOnly: widget.readOnly,
                  ),
                ],
              ],
            ),
            const SizedBox(height: 24),

            // Section Occupant
            FormSection(
              title: 'Occupant',
              icon: Icons.person,
              children: [
                CustomTextField(
                  controller: _nameController,
                  label: "Nom de l'occupant",
                  isRequired: _emailController.text.trim().isNotEmpty,
                  showLabel: false,
                  readOnly: widget.readOnly,
                  validator: _validateNomOccupant,
                ),
                const SizedBox(height: 16),
                // Layout responsive : 1 ligne desktop, 2 lignes mobile
                _isMobile(context)
                    ? Column(
                        children: [
                          CustomTextField(
                            controller: _emailController,
                            label: "Email",
                            showLabel: false,
                            keyboardType: TextInputType.emailAddress,
                            readOnly: widget.readOnly,
                            validator: _validateEmail,
                            prefixIcon: Icons.email,
                          ),
                          const SizedBox(height: 16),
                          CustomTextField(
                            controller: _phoneController,
                            label: "Téléphone",
                            showLabel: false,
                            keyboardType: TextInputType.phone,
                            readOnly: widget.readOnly,
                            prefixIcon: Icons.phone,
                          ),
                        ],
                      )
                    : Row(
                        children: [
                          Expanded(
                            child: CustomTextField(
                              controller: _emailController,
                              label: "Email",
                              showLabel: false,
                              keyboardType: TextInputType.emailAddress,
                              readOnly: widget.readOnly,
                              validator: _validateEmail,
                              prefixIcon: Icons.email,
                            ),
                          ),
                          const SizedBox(width: 12),
                          Expanded(
                            child: CustomTextField(
                              controller: _phoneController,
                              label: "Téléphone",
                              showLabel: false,
                              keyboardType: TextInputType.phone,
                              readOnly: widget.readOnly,
                              prefixIcon: Icons.phone,
                            ),
                          ),
                        ],
                      ),
              ],
            ),
            const SizedBox(height: 24),

            // Section Règlement et Remarque
            FormSection(
              title: (_selectedPassageType == 1 || _selectedPassageType == 5)
                  ? 'Règlement et Note'
                  : 'Note',
              icon: Icons.note,
              children: [
                // Afficher montant et type de règlement seulement pour fkType 1 (Effectué) ou 5 (Lot)
                if (_selectedPassageType == 1 || _selectedPassageType == 5) ...[
                  Row(
                    children: [
                      Expanded(
                        child: CustomTextField(
                          controller: _montantController,
                          label: "Montant",
                          isRequired: true,
                          showLabel: false,
                          hintText: "0.00",
                          textAlign: TextAlign.right,
                          keyboardType: const TextInputType.numberWithOptions(
                              decimal: true),
                          readOnly: widget.readOnly,
                          validator: _validateMontant,
                          prefixIcon: Icons.euro,
                        ),
                      ),
                      const SizedBox(width: 12),
                      Expanded(
                        child: DropdownButtonFormField<int>(
                          value: _fkTypeReglement,
                          decoration: const InputDecoration(
                            labelText: "Type de règlement *",
                            border: OutlineInputBorder(),
                          ),
                          items: AppKeys.typesReglements.entries.map((entry) {
                            return DropdownMenuItem<int>(
                              value: entry.key,
                              child: Row(
                                children: [
                                  Icon(
                                    entry.value['icon_data'] as IconData,
                                    color: Color(entry.value['couleur'] as int),
                                    size: 16,
                                  ),
                                  const SizedBox(width: 8),
                                  Text(entry.value['titre'] as String),
                                ],
                              ),
                            );
                          }).toList(),
                          onChanged: widget.readOnly
                              ? null
                              : (value) {
                                  setState(() {
                                    _fkTypeReglement = value!;
                                  });
                                },
                          validator: (_selectedPassageType == 1 ||
                                  _selectedPassageType == 5)
                              ? (value) {
                                  if (value == null || value < 1 || value > 3) {
                                    return 'Type de règlement requis';
                                  }
                                  return null;
                                }
                              : null,
                        ),
                      ),
                    ],
                  ),
                  const SizedBox(height: 16),
                ],
                CustomTextField(
                  controller: _remarqueController,
                  label: "Note",
                  showLabel: false,
                  hintText: "Commentaire sur le passage...",
                  maxLines: 2,
                  readOnly: widget.readOnly,
                ),
              ],
            ),
          ],
        ),
      );
    } catch (e, stackTrace) {
      debugPrint('=== ERREUR _buildPassageForm ===');
      debugPrint('Erreur: $e');
      debugPrint('StackTrace: $stackTrace');

      return Container(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            const Icon(Icons.error, color: Colors.red),
            const SizedBox(height: 8),
            Text('Erreur dans le formulaire: $e'),
          ],
        ),
      );
    }
  }

  Future<void> _selectDate() async {
    final DateTime? picked = await showDatePicker(
      context: context,
      initialDate: _passedAt,
      firstDate: DateTime(2020),
      lastDate: DateTime(2030),
    );
    if (picked != null) {
      setState(() {
        _passedAt = DateTime(
          picked.year,
          picked.month,
          picked.day,
          _passedAt.hour,
          _passedAt.minute,
        );
        _dateController.text =
            '${_passedAt.day.toString().padLeft(2, '0')}/${_passedAt.month.toString().padLeft(2, '0')}/${_passedAt.year}';
      });
    }
  }

  Future<void> _selectTime() async {
    final TimeOfDay? picked = await showTimePicker(
      context: context,
      initialTime: TimeOfDay.fromDateTime(_passedAt),
    );
    if (picked != null) {
      setState(() {
        _passedAt = DateTime(
          _passedAt.year,
          _passedAt.month,
          _passedAt.day,
          picked.hour,
          picked.minute,
        );
        _timeController.text =
            '${_passedAt.hour.toString().padLeft(2, '0')}:${_passedAt.minute.toString().padLeft(2, '0')}';
      });
    }
  }

  // Méthode pour détecter si on est sur mobile
  bool _isMobile(BuildContext context) {
    // Détecter si on est sur mobile natif ou web mobile (largeur < 600px)
    return Theme.of(context).platform == TargetPlatform.iOS ||
        Theme.of(context).platform == TargetPlatform.android ||
        (kIsWeb && MediaQuery.of(context).size.width < 600);
  }

  // Méthode pour construire l'en-tête du formulaire
  Widget _buildHeader() {
    final theme = Theme.of(context);

    return Container(
      decoration: BoxDecoration(
        color: _selectedPassageType != null &&
                AppKeys.typesPassages.containsKey(_selectedPassageType)
            ? Color(AppKeys.typesPassages[_selectedPassageType]!['couleur2']
                        as int? ??
                    0xFF000000)
                .withOpacity(0.1)
            : null,
        borderRadius: BorderRadius.circular(8),
      ),
      padding: const EdgeInsets.all(12),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Expanded(
            child: Row(
              children: [
                Icon(
                  widget.passage == null ? Icons.add_circle : Icons.edit,
                  color: _selectedPassageType != null &&
                          AppKeys.typesPassages
                              .containsKey(_selectedPassageType)
                      ? Color(AppKeys.typesPassages[_selectedPassageType]![
                              'couleur2'] as int? ??
                          0xFF000000)
                      : theme.colorScheme.primary,
                ),
                const SizedBox(width: 8),
                Flexible(
                  child: Text(
                    widget.title,
                    style: theme.textTheme.headlineSmall?.copyWith(
                      fontWeight: FontWeight.bold,
                      color: _selectedPassageType != null &&
                              AppKeys.typesPassages
                                  .containsKey(_selectedPassageType)
                          ? Color(AppKeys.typesPassages[_selectedPassageType]![
                                  'couleur2'] as int? ??
                              0xFF000000)
                          : theme.colorScheme.primary,
                    ),
                    overflow: TextOverflow.ellipsis,
                  ),
                ),
                if (_selectedPassageType != null &&
                    AppKeys.typesPassages
                        .containsKey(_selectedPassageType)) ...[
                  const SizedBox(width: 12),
                  Icon(
                    AppKeys.typesPassages[_selectedPassageType]!['icon_data']
                            as IconData? ??
                        Icons.help,
                    color: Color(
                        AppKeys.typesPassages[_selectedPassageType]!['couleur2']
                                as int? ??
                            0xFF000000),
                    size: 20,
                  ),
                  const SizedBox(width: 4),
                  Text(
                    AppKeys.typesPassages[_selectedPassageType]!['titre']
                            as String? ??
                        'Inconnu',
                    style: theme.textTheme.titleMedium?.copyWith(
                      fontWeight: FontWeight.w600,
                      color: Color(AppKeys.typesPassages[_selectedPassageType]![
                              'couleur2'] as int? ??
                          0xFF000000),
                    ),
                  ),
                ],
              ],
            ),
          ),
          IconButton(
            icon: const Icon(Icons.close),
            onPressed: _isSubmitting ? null : () {
              Navigator.of(context, rootNavigator: false).pop();
            },
          ),
        ],
      ),
    );
  }

  // Méthode pour construire le contenu principal
  Widget _buildContent() {
    return SingleChildScrollView(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          if (!_showForm) ...[
            () {
              debugPrint('Building passage type selection...');
              return _buildPassageTypeSelection();
            }(),
          ] else ...[
            () {
              debugPrint('Building passage form...');
              return _buildPassageForm();
            }(),
          ],
        ],
      ),
    );
  }

  // Méthode pour construire les boutons du footer
  Widget _buildFooterButtons() {
    final theme = Theme.of(context);

    return Row(
      mainAxisAlignment: MainAxisAlignment.end,
      children: [
        TextButton(
          onPressed: _isSubmitting ? null : () {
            Navigator.of(context, rootNavigator: false).pop();
          },
          child: const Text('Annuler'),
        ),
        const SizedBox(width: 16),
        if (!widget.readOnly && _showForm && _selectedPassageType != null)
          ElevatedButton.icon(
            onPressed: _isSubmitting ? null : _handleSubmit,
            icon: _isSubmitting
                ? const SizedBox(
                    width: 16,
                    height: 16,
                    child: CircularProgressIndicator(strokeWidth: 2),
                  )
                : Icon(widget.passage == null ? Icons.add : Icons.save),
            label: Text(_isSubmitting
                ? 'Enregistrement...'
                : (widget.passage == null ? 'Créer' : 'Enregistrer')),
            style: ElevatedButton.styleFrom(
              backgroundColor: theme.colorScheme.primary,
              foregroundColor: Colors.white,
            ),
          ),
      ],
    );
  }

  // Méthode pour construire le contenu du Dialog
  Widget _buildDialogContent() {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        // Header
        _buildHeader(),
        const Divider(),

        // Contenu
        Expanded(
          child: _buildContent(),
        ),

        const SizedBox(height: 24),

        // Footer
        _buildFooterButtons(),
      ],
    );
  }

  // Méthode pour construire l'AppBar mobile
  AppBar _buildMobileAppBar() {
    final theme = Theme.of(context);
    final typeColor = _selectedPassageType != null &&
            AppKeys.typesPassages.containsKey(_selectedPassageType)
        ? Color(
            AppKeys.typesPassages[_selectedPassageType]!['couleur2'] as int? ??
                0xFF000000)
        : theme.colorScheme.primary;

    return AppBar(
      backgroundColor: typeColor.withOpacity(0.1),
      elevation: 0,
      leading: IconButton(
        icon: Icon(Icons.close, color: typeColor),
        onPressed: _isSubmitting ? null : () {
          Navigator.of(context, rootNavigator: false).pop();
        },
      ),
      title: Row(
        children: [
          Icon(
            widget.passage == null ? Icons.add_circle : Icons.edit,
            color: typeColor,
            size: 24,
          ),
          const SizedBox(width: 8),
          Expanded(
            child: Text(
              widget.title,
              style: TextStyle(
                color: typeColor,
                fontWeight: FontWeight.bold,
                fontSize: AppTheme.r(context, 18),
              ),
              overflow: TextOverflow.ellipsis,
            ),
          ),
        ],
      ),
      actions: _selectedPassageType != null &&
              AppKeys.typesPassages.containsKey(_selectedPassageType)
          ? [
              Padding(
                padding: const EdgeInsets.only(right: 8),
                child: Row(
                  children: [
                    Icon(
                      AppKeys.typesPassages[_selectedPassageType]!['icon_data']
                              as IconData? ??
                          Icons.help,
                      color: typeColor,
                      size: 20,
                    ),
                    const SizedBox(width: 4),
                    Text(
                      AppKeys.typesPassages[_selectedPassageType]!['titre']
                              as String? ??
                          'Inconnu',
                      style: TextStyle(
                        fontWeight: FontWeight.w600,
                        color: typeColor,
                        fontSize: AppTheme.r(context, 14),
                      ),
                    ),
                  ],
                ),
              ),
            ]
          : null,
    );
  }

  /// Tente d'effectuer un paiement Tap to Pay avec un passage déjà sauvegardé
  Future<bool> _attemptTapToPayWithPassage(PassageModel passage, double montant) async {
    try {
      // Afficher le dialog de paiement avec l'ID réel du passage
      final result = await showDialog<bool>(
        context: context,
        barrierDismissible: false,
        builder: (context) => _TapToPayFlowDialog(
          amount: montant,
          passageId: passage.id,  // ID réel du passage sauvegardé
          onSuccess: (paymentIntentId) {
            // Mettre à jour le passage avec le stripe_payment_id
            final updatedPassage = passage.copyWith(
              stripePaymentId: paymentIntentId,
            );

            // Envoyer la mise à jour à l'API (sera fait de manière asynchrone)
            widget.passageRepository.updatePassage(updatedPassage).then((_) {
              debugPrint('✅ Passage mis à jour avec stripe_payment_id: $paymentIntentId');
            }).catchError((error) {
              debugPrint('❌ Erreur mise à jour passage: $error');
            });

            setState(() {
              _stripePaymentIntentId = paymentIntentId;
            });
          },
        ),
      );

      // Si paiement réussi, afficher le message de succès et fermer
      if (result == true && mounted) {
        await ResultDialog.show(
          context: context,
          success: true,
          message: "Paiement effectué avec succès",
        );

        if (mounted) {
          Navigator.of(context, rootNavigator: false).pop();
          widget.onSuccess?.call();
        }
        return true;
      }

      return false;
    } catch (e) {
      debugPrint('Erreur Tap to Pay: $e');
      if (mounted) {
        await ResultDialog.show(
          context: context,
          success: false,
          message: ApiException.fromError(e).message,
        );
      }
      return false;
    }
  }

  @override
  Widget build(BuildContext context) {
    try {
      debugPrint('=== DEBUT PassageFormDialog.build ===');

      final isMobile = _isMobile(context);
      debugPrint('Platform mobile détectée: $isMobile');

      if (isMobile) {
        // Mode plein écran pour mobile
        return Scaffold(
          appBar: _buildMobileAppBar(),
          body: SafeArea(
            child: SingleChildScrollView(
              padding: const EdgeInsets.all(16),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  // Contenu du formulaire
                  if (!_showForm) ...[
                    _buildPassageTypeSelection(),
                  ] else ...[
                    _buildPassageForm(),
                  ],

                  // Boutons en bas du scroll
                  if (_showForm && _selectedPassageType != null) ...[
                    const SizedBox(height: 32),
                    _buildFooterButtons(),
                    const SizedBox(height: 16), // Padding supplémentaire pour le confort
                  ],
                ],
              ),
            ),
          ),
        );
      } else {
        // Mode Dialog pour desktop/tablette
        return Dialog(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(16),
          ),
          insetPadding: const EdgeInsets.all(24),
          child: Container(
            width: MediaQuery.of(context).size.width * 0.6,
            constraints: const BoxConstraints(
              maxWidth: 800,
              maxHeight: 900,
            ),
            padding: const EdgeInsets.all(24),
            child: _buildDialogContent(),
          ),
        );
      }
    } catch (e, stackTrace) {
      debugPrint('=== ERREUR PassageFormDialog.build ===');
      debugPrint('Erreur: $e');
      debugPrint('StackTrace: $stackTrace');

      // Retourner un widget d'erreur simple
      return Dialog(
        child: Container(
          padding: const EdgeInsets.all(16),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              const Icon(Icons.error, color: Colors.red, size: 48),
              const SizedBox(height: 16),
              Text('Erreur lors de l\'affichage du formulaire: $e'),
              const SizedBox(height: 16),
              ElevatedButton(
                onPressed: () => Navigator.of(context).pop(),
                child: const Text('Fermer'),
              ),
            ],
          ),
        ),
      );
    }
  }
}

/// Dialog pour gérer le flow de paiement Tap to Pay
class _TapToPayFlowDialog extends StatefulWidget {
  final double amount;
  final int passageId;
  final void Function(String paymentIntentId)? onSuccess;

  const _TapToPayFlowDialog({
    required this.amount,
    required this.passageId,
    this.onSuccess,
  });

  @override
  State<_TapToPayFlowDialog> createState() => _TapToPayFlowDialogState();
}

class _TapToPayFlowDialogState extends State<_TapToPayFlowDialog> {
  String _currentState = 'confirming';
  String? _paymentIntentId;
  String? _errorMessage;
  StreamSubscription<TapToPayStatus>? _statusSubscription;

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

  @override
  void dispose() {
    _statusSubscription?.cancel();
    super.dispose();
  }

  void _listenToPaymentStatus() {
    _statusSubscription = StripeTapToPayService.instance.paymentStatusStream.listen(
      (status) {
        if (!mounted) return;

        setState(() {
          switch (status.type) {
            case TapToPayStatusType.ready:
              _currentState = 'ready';
              break;
            case TapToPayStatusType.awaitingTap:
              _currentState = 'awaiting_tap';
              break;
            case TapToPayStatusType.processing:
              _currentState = 'processing';
              break;
            case TapToPayStatusType.confirming:
              _currentState = 'confirming';
              break;
            case TapToPayStatusType.success:
              _currentState = 'success';
              _paymentIntentId = status.paymentIntentId;
              _handleSuccess();
              break;
            case TapToPayStatusType.error:
              _currentState = 'error';
              _errorMessage = status.message;
              break;
            case TapToPayStatusType.cancelled:
              Navigator.pop(context, false);
              break;
          }
        });
      },
    );
  }

  void _handleSuccess() {
    if (_paymentIntentId != null) {
      widget.onSuccess?.call(_paymentIntentId!);
      // Attendre un peu pour montrer le succès
      Future.delayed(const Duration(seconds: 2), () {
        if (mounted) {
          Navigator.pop(context, true);
        }
      });
    }
  }

  Future<void> _startPayment() async {
    setState(() {
      _currentState = 'initializing';
      _errorMessage = null;
    });

    try {
      // Initialiser le service si nécessaire
      if (!StripeTapToPayService.instance.isInitialized) {
        final initialized = await StripeTapToPayService.instance.initialize();
        if (!initialized) {
          throw Exception('Impossible d\'initialiser Tap to Pay');
        }
      }

      // Vérifier que le service est prêt
      if (!StripeTapToPayService.instance.isReadyForPayments()) {
        throw Exception('L\'appareil n\'est pas prêt pour les paiements');
      }

      // Créer le PaymentIntent avec l'ID du passage dans les metadata
      final paymentIntent = await StripeTapToPayService.instance.createPaymentIntent(
        amountInCents: (widget.amount * 100).round(),
        description: 'Calendrier pompiers${widget.passageId > 0 ? " - Passage #${widget.passageId}" : ""}',
        metadata: {
          'type': 'tap_to_pay',
          'passage_id': widget.passageId.toString(),
          'amicale_id': CurrentAmicaleService.instance.amicaleId.toString(),
          'member_id': CurrentUserService.instance.userId.toString(),
        },
      );

      if (paymentIntent == null) {
        throw Exception('Impossible de créer le paiement');
      }

      _paymentIntentId = paymentIntent.paymentIntentId;

      // Collecter le paiement
      final collected = await StripeTapToPayService.instance.collectPayment(paymentIntent);
      if (!collected) {
        throw Exception('Échec de la collecte du paiement');
      }

      // Confirmer le paiement
      final confirmed = await StripeTapToPayService.instance.confirmPayment(paymentIntent);
      if (!confirmed) {
        throw Exception('Échec de la confirmation du paiement');
      }

    } catch (e) {
      // Analyser le type d'erreur pour afficher un message clair
      final errorMsg = e.toString().toLowerCase();

      String userMessage;
      bool shouldCancelPayment = true;

      if (errorMsg.contains('canceled') || errorMsg.contains('cancelled')) {
        // Annulation volontaire par l'utilisateur
        userMessage = 'Paiement annulé';

      } else if (errorMsg.contains('cardreadtimedout') || errorMsg.contains('timed out')) {
        // Timeout de lecture NFC
        userMessage = 'Lecture de la carte impossible.\n\n'
            'Conseils :\n'
            '• Maintenez la carte contre le dos du téléphone\n'
            '• Ne bougez pas jusqu\'à confirmation\n'
            '• Retirez la coque si nécessaire\n'
            '• Essayez différentes positions sur le téléphone';

      } else if (errorMsg.contains('already') && errorMsg.contains('payment')) {
        // PaymentIntent existe déjà
        userMessage = 'Un paiement est déjà en cours pour ce passage.\n'
            'Veuillez réessayer dans quelques instants.';
        shouldCancelPayment = false; // Déjà en cours, pas besoin d'annuler

      } else {
        // Autre erreur technique
        userMessage = 'Erreur lors du paiement.\n\n$e';
      }

      // Annuler le PaymentIntent si créé pour permettre une nouvelle tentative
      if (shouldCancelPayment && _paymentIntentId != null) {
        StripeTapToPayService.instance.cancelPayment(_paymentIntentId!).catchError((cancelError) {
          debugPrint('⚠️ Erreur annulation PaymentIntent: $cancelError');
        });
      }

      setState(() {
        _currentState = 'error';
        _errorMessage = userMessage;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);

    Widget content;
    List<Widget> actions = [];

    switch (_currentState) {
      case 'confirming':
        content = Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(Icons.contactless, size: 64, color: theme.colorScheme.primary),
            const SizedBox(height: 24),
            Text(
              'Paiement par carte sans contact',
              style: theme.textTheme.headlineSmall,
            ),
            const SizedBox(height: 16),
            Text(
              'Montant: ${widget.amount.toStringAsFixed(2)}€',
              style: theme.textTheme.titleLarge?.copyWith(
                fontWeight: FontWeight.bold,
                color: theme.colorScheme.primary,
              ),
            ),
            const SizedBox(height: 24),
            const Text(
              'Le client va payer par carte bancaire sans contact.\n'
              'Son téléphone ou sa carte sera présenté(e) sur cet appareil.',
              textAlign: TextAlign.center,
            ),
          ],
        );
        actions = [
          TextButton(
            onPressed: () => Navigator.pop(context, false),
            child: const Text('Annuler'),
          ),
          ElevatedButton.icon(
            onPressed: _startPayment,
            icon: const Icon(Icons.payment),
            label: const Text('Lancer le paiement'),
          ),
        ];
        break;

      case 'initializing':
        content = Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            const CircularProgressIndicator(),
            const SizedBox(height: 24),
            Text(
              'Initialisation du terminal...',
              style: theme.textTheme.titleMedium,
            ),
          ],
        );
        break;

      case 'awaiting_tap':
        content = Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(
              Icons.tap_and_play,
              size: 80,
              color: theme.colorScheme.primary,
            ),
            const SizedBox(height: 24),
            Text(
              'Présentez la carte',
              style: theme.textTheme.headlineSmall,
            ),
            const SizedBox(height: 16),
            const LinearProgressIndicator(),
            const SizedBox(height: 16),
            Text(
              'Montant: ${widget.amount.toStringAsFixed(2)}€',
              style: theme.textTheme.titleMedium,
            ),
          ],
        );
        actions = [
          TextButton(
            onPressed: () {
              if (_paymentIntentId != null) {
                StripeTapToPayService.instance.cancelPayment(_paymentIntentId!);
              }
              Navigator.pop(context, false);
            },
            child: const Text('Annuler'),
          ),
        ];
        break;

      case 'processing':
        content = Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            const CircularProgressIndicator(),
            const SizedBox(height: 24),
            Text(
              'Traitement du paiement...',
              style: theme.textTheme.titleMedium,
            ),
            const SizedBox(height: 8),
            const Text('Ne pas retirer la carte'),
          ],
        );
        break;

      case 'success':
        content = Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            const Icon(
              Icons.check_circle,
              size: 80,
              color: Colors.green,
            ),
            const SizedBox(height: 24),
            Text(
              'Paiement réussi !',
              style: theme.textTheme.headlineSmall?.copyWith(
                color: Colors.green,
              ),
            ),
            const SizedBox(height: 16),
            Text(
              '${widget.amount.toStringAsFixed(2)}€ payé par carte',
              style: theme.textTheme.titleMedium,
            ),
          ],
        );
        break;

      case 'error':
        content = Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            const Icon(
              Icons.error_outline,
              size: 80,
              color: Colors.red,
            ),
            const SizedBox(height: 24),
            Text(
              'Échec du paiement',
              style: theme.textTheme.headlineSmall?.copyWith(
                color: Colors.red,
              ),
            ),
            const SizedBox(height: 16),
            Text(
              _errorMessage ?? 'Une erreur est survenue',
              textAlign: TextAlign.center,
              style: theme.textTheme.bodyMedium,
            ),
          ],
        );
        actions = [
          TextButton(
            onPressed: () => Navigator.pop(context, false),
            child: const Text('Annuler'),
          ),
          ElevatedButton.icon(
            onPressed: _startPayment,
            icon: const Icon(Icons.refresh),
            label: const Text('Réessayer'),
          ),
        ];
        break;

      default:
        content = const Center(child: CircularProgressIndicator());
    }

    return AlertDialog(
      title: Row(
        children: [
          Icon(Icons.contactless, color: theme.colorScheme.primary),
          const SizedBox(width: 8),
          const Text('Paiement sans contact'),
        ],
      ),
      content: Container(
        constraints: const BoxConstraints(maxWidth: 400),
        child: content,
      ),
      actions: actions.isEmpty ? null : actions,
    );
  }
}
