import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:go_router/go_router.dart';
import 'package:image_picker/image_picker.dart';
import 'package:intl/intl.dart';
import 'dart:math' as math;
import 'dart:io';
import '../models/am_registration_data.dart' show kAmCapaciteAccueilMax;
import '../models/card_assets.dart';
import '../config/display_config.dart';
import '../utils/nir_utils.dart';
import '../utils/name_format_utils.dart';
import 'custom_app_text_field.dart';
import 'nir_text_field.dart';
import 'form_field_wrapper.dart';
import 'app_custom_checkbox.dart';
import 'hover_relief_widget.dart';
import 'custom_navigation_button.dart';
import 'registration_photo_slot.dart';

/// Données pour le formulaire d'informations professionnelles
class ProfessionalInfoData {
  final String? photoPath;
  final File? photoFile;
  final Uint8List? photoBytes;
  final String? photoFilename;
  final bool photoConsent;
  final DateTime? dateOfBirth;
  final String birthCity;
  final String birthCountry;
  final String nir;
  final String agrementNumber;
  /// Date d'obtention de l'agrément (obligatoire, API `date_agrement`).
  final DateTime? agreementDate;
  final int? capacity;
  final int? placesAvailable;

  ProfessionalInfoData({
    this.photoPath,
    this.photoFile,
    this.photoBytes,
    this.photoFilename,
    this.photoConsent = false,
    this.dateOfBirth,
    this.birthCity = '',
    this.birthCountry = '',
    this.nir = '',
    this.agrementNumber = '',
    this.agreementDate,
    this.capacity,
    this.placesAvailable,
  });
}

/// Widget générique pour le formulaire d'informations professionnelles
/// Utilisé pour l'inscription des Assistantes Maternelles
/// Supporte mode éditable et readonly, responsive mobile/desktop
class ProfessionalInfoFormScreen extends StatefulWidget {
  final DisplayMode mode;
  final String stepText;
  final String title;
  final CardColorHorizontal cardColor;
  final ProfessionalInfoData? initialData;
  final String previousRoute;
  final Function(ProfessionalInfoData) onSubmit;
  final Future<void> Function()? onPickPhoto;
  final bool embedContentOnly;
  final VoidCallback? onEdit;

  const ProfessionalInfoFormScreen({
    super.key,
    this.mode = DisplayMode.editable,
    required this.stepText,
    required this.title,
    required this.cardColor,
    this.initialData,
    required this.previousRoute,
    required this.onSubmit,
    this.onPickPhoto,
    this.embedContentOnly = false,
    this.onEdit,
  });

  @override
  State<ProfessionalInfoFormScreen> createState() => _ProfessionalInfoFormScreenState();
}

class _ProfessionalInfoFormScreenState extends State<ProfessionalInfoFormScreen> {
  final _formKey = GlobalKey<FormState>();

  /// Ordre Tab explicite : sans cela, la zone photo (InkWell) peut s’insérer entre pays et NIR.
  static const double _kTabPhotoPick = 1;
  static const double _kTabDateBirth = 2;
  static const double _kTabBirthCity = 3;
  static const double _kTabBirthCountry = 4;
  static const double _kTabNir = 5;
  static const double _kTabAgrement = 6;
  static const double _kTabAgreementDate = 7;
  static const double _kTabCapacity = 8;
  static const double _kTabPlaces = 9;
  static const double _kTabChevronNext = 10;
  static const double _kTabChevronPrev = 11;

  final _dateOfBirthController = TextEditingController();
  final _birthCityController = TextEditingController();
  final _birthCountryController = TextEditingController();
  final _nirController = TextEditingController();
  final _agrementController = TextEditingController();
  final _agreementDateController = TextEditingController();
  final _capacityController = TextEditingController();
  final _placesAvailableController = TextEditingController();

  FocusNode? _birthCityFocus;
  FocusNode? _birthCountryFocus;
  FocusNode? _nirFocus;

  DateTime? _selectedDate;
  DateTime? _selectedAgreementDate;
  String? _photoPathFramework;
  File? _photoFile;
  Uint8List? _photoBytes;
  String? _photoFilename;
  bool _photoConsent = false;

  bool get _hasRealPhoto =>
      (_photoBytes != null && _photoBytes!.isNotEmpty) ||
      _photoFile != null ||
      (_photoPathFramework != null &&
          _photoPathFramework!.isNotEmpty &&
          !_photoPathFramework!.startsWith('assets/'));

  @override
  void initState() {
    super.initState();
    _applyInitialData(widget.initialData);

    if (widget.mode == DisplayMode.editable) {
      _birthCityFocus = FocusNode();
      _birthCountryFocus = FocusNode();
      _nirFocus = FocusNode();
      _birthCityFocus!.addListener(_onBirthCityFocusChange);
      _birthCountryFocus!.addListener(_onBirthCountryFocusChange);
    }
  }

  @override
  void didUpdateWidget(covariant ProfessionalInfoFormScreen oldWidget) {
    super.didUpdateWidget(oldWidget);
    final next = widget.initialData;
    final prev = oldWidget.initialData;
    if (next == null) return;
    if (prev == null ||
        prev.dateOfBirth != next.dateOfBirth ||
        prev.agreementDate != next.agreementDate ||
        prev.placesAvailable != next.placesAvailable ||
        prev.capacity != next.capacity ||
        prev.nir != next.nir ||
        prev.birthCity != next.birthCity ||
        prev.birthCountry != next.birthCountry ||
        prev.agrementNumber != next.agrementNumber ||
        prev.photoPath != next.photoPath ||
        prev.photoConsent != next.photoConsent) {
      _applyInitialData(next);
    }
  }

  void _applyInitialData(ProfessionalInfoData? data) {
    if (data == null) return;
    _selectedDate = data.dateOfBirth;
    _dateOfBirthController.text = data.dateOfBirth != null
        ? DateFormat('dd/MM/yyyy').format(data.dateOfBirth!)
        : '';
    _birthCityController.text = data.birthCity;
    _birthCountryController.text = data.birthCountry;
    final nirRaw = nirToRaw(data.nir);
    _nirController.text = nirRaw.length == 15 ? formatNir(nirRaw) : data.nir;
    _agrementController.text = data.agrementNumber;
    _selectedAgreementDate = data.agreementDate;
    _agreementDateController.text = data.agreementDate != null
        ? DateFormat('dd/MM/yyyy').format(data.agreementDate!)
        : '';
    _capacityController.text = data.capacity?.toString() ?? '';
    _placesAvailableController.text = data.placesAvailable?.toString() ?? '';
    _photoPathFramework = data.photoPath;
    _photoFile = data.photoFile;
    _photoBytes = data.photoBytes;
    _photoFilename = data.photoFilename;
    _photoConsent = data.photoConsent;
  }

  void _onBirthCityFocusChange() {
    if (_birthCityFocus == null || _birthCityFocus!.hasFocus) return;
    _applyPlaceNameFormat(_birthCityController);
  }

  void _onBirthCountryFocusChange() {
    if (_birthCountryFocus == null || _birthCountryFocus!.hasFocus) return;
    _applyPlaceNameFormat(_birthCountryController);
  }

  void _applyPlaceNameFormat(TextEditingController controller) {
    final formatted = formatPersonNameCase(controller.text);
    if (formatted == controller.text) return;
    controller.value = TextEditingValue(
      text: formatted,
      selection: TextSelection.collapsed(offset: formatted.length),
    );
  }

  @override
  void dispose() {
    _birthCityFocus?.removeListener(_onBirthCityFocusChange);
    _birthCountryFocus?.removeListener(_onBirthCountryFocusChange);
    _birthCityFocus?.dispose();
    _birthCountryFocus?.dispose();
    _nirFocus?.dispose();
    _dateOfBirthController.dispose();
    _birthCityController.dispose();
    _birthCountryController.dispose();
    _nirController.dispose();
    _agrementController.dispose();
    _agreementDateController.dispose();
    _capacityController.dispose();
    _placesAvailableController.dispose();
    super.dispose();
  }

  String? _validateBirthCity(String? v) {
    final t = (v ?? '').trim();
    if (t.isEmpty) return 'Ville requise';
    if (t.length < 2) return 'Au moins 2 caractères';
    return null;
  }

  String? _validateBirthCountry(String? v) {
    final t = (v ?? '').trim();
    if (t.isEmpty) return 'Pays requis';
    if (t.length < 2) return 'Au moins 2 caractères';
    return null;
  }

  String? _validatePlacesAvailable(String? v) {
    if (v == null || v.isEmpty) return 'Places disponibles requises';
    final n = int.tryParse(v);
    if (n == null || n < 0) return 'Nombre entre 0 et la capacité';
    if (n > kAmCapaciteAccueilMax) return 'Maximum $kAmCapaciteAccueilMax';
    final cap = int.tryParse(_capacityController.text);
    if (cap != null && n > cap) return 'Ne peut pas dépasser la capacité';
    return null;
  }

  Future<void> _selectDate(BuildContext context) async {
    final DateTime? picked = await showDatePicker(
      context: context,
      initialDate: _selectedDate ?? DateTime.now().subtract(const Duration(days: 365 * 25)),
      firstDate: DateTime(1920, 1),
      lastDate: DateTime.now().subtract(const Duration(days: 365 * 18)),
      locale: const Locale('fr', 'FR'),
    );
    if (picked != null && picked != _selectedDate) {
      setState(() {
        _selectedDate = picked;
        _dateOfBirthController.text = DateFormat('dd/MM/yyyy').format(picked);
      });
    }
  }

  Future<void> _selectAgreementDate(BuildContext context) async {
    final DateTime? picked = await showDatePicker(
      context: context,
      initialDate: _selectedAgreementDate ?? DateTime.now().subtract(const Duration(days: 365 * 5)),
      firstDate: DateTime(1970, 1),
      lastDate: DateTime.now(),
      locale: const Locale('fr', 'FR'),
    );
    if (picked != null) {
      setState(() {
        _selectedAgreementDate = picked;
        _agreementDateController.text = DateFormat('dd/MM/yyyy').format(picked);
      });
    }
  }

  Future<void> _pickPhoto() async {
    if (widget.onPickPhoto != null) {
      await widget.onPickPhoto!();
      return;
    }

    final picker = ImagePicker();
    try {
      final XFile? picked = await picker.pickImage(
        source: ImageSource.gallery,
        imageQuality: 75,
        maxWidth: 1200,
        maxHeight: 1200,
      );
      if (picked == null) return;
      final bytes = await picked.readAsBytes();
      if (bytes.isEmpty) return;

      File? file;
      if (!kIsWeb) {
        try {
          final f = File(picked.path);
          if (await f.exists()) file = f;
        } catch (_) {}
      }

      final name = picked.name.trim();
      setState(() {
        _photoBytes = bytes;
        _photoFile = file;
        _photoPathFramework = null;
        _photoFilename = name.isNotEmpty ? name : 'photo_am.jpg';
      });
    } catch (_) {}
  }

  void _clearRegistrationPhoto() {
    setState(() {
      _photoBytes = null;
      _photoFile = null;
      _photoPathFramework = null;
      _photoFilename = null;
      _photoConsent = false;
    });
  }

  void _submitForm() {
    _applyPlaceNameFormat(_birthCityController);
    _applyPlaceNameFormat(_birthCountryController);
    if (_formKey.currentState!.validate()) {
      if (!_hasRealPhoto) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Veuillez ajouter une photo de profil.')),
        );
        return;
      }
      if (!_photoConsent) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Veuillez accepter le consentement photo pour continuer.')),
        );
        return;
      }

      final data = ProfessionalInfoData(
        photoPath: _photoBytes != null ? null : _photoPathFramework,
        photoFile: _photoFile,
        photoBytes: _photoBytes,
        photoFilename: _photoFilename,
        photoConsent: _photoConsent,
        dateOfBirth: _selectedDate,
        birthCity: _birthCityController.text.trim(),
        birthCountry: _birthCountryController.text.trim(),
        nir: normalizeNir(_nirController.text),
        agrementNumber: _agrementController.text,
        agreementDate: _selectedAgreementDate,
        capacity: int.tryParse(_capacityController.text),
        placesAvailable: int.tryParse(_placesAvailableController.text),
      );

      widget.onSubmit(data);
    }
  }

  @override
  Widget build(BuildContext context) {
    final screenSize = MediaQuery.of(context).size;
    final config = DisplayConfig.fromContext(context, mode: widget.mode);

    if (widget.embedContentOnly) {
      return _buildCard(context, config, screenSize);
    }

    return FocusTraversalGroup(
      policy: OrderedTraversalPolicy(),
      child: Scaffold(
        body: Stack(
          children: [
            Positioned.fill(
              child: Image.asset('assets/images/paper2.png', fit: BoxFit.cover, repeat: ImageRepeat.repeat),
            ),
            Center(
              child: SingleChildScrollView(
                padding: EdgeInsets.symmetric(vertical: config.isMobile ? 40.0 : 28.0),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(
                      widget.stepText,
                      style: GoogleFonts.merienda(
                        fontSize: config.isMobile ? 13 : 16,
                        color: Colors.black54,
                      ),
                    ),
                    SizedBox(height: config.isMobile ? 6 : 10),
                    Text(
                      widget.title,
                      style: GoogleFonts.merienda(
                        fontSize: config.isMobile ? 18 : 24,
                        fontWeight: FontWeight.bold,
                        color: Colors.black87,
                      ),
                      textAlign: TextAlign.center,
                    ),
                    SizedBox(height: config.isMobile ? 16 : 20),
                    _buildCard(context, config, screenSize),

                    // Boutons mobile sous la carte
                    if (config.isMobile) ...[
                      const SizedBox(height: 20),
                      _buildMobileButtons(context, config, screenSize),
                      const SizedBox(height: 10),
                    ],
                  ],
                ),
              ),
            ),
          // Chevrons desktop : visuellement sur les côtés ; ordre Tab 10–11 = après « Places disponibles ».
          if (!config.isMobile) ...[
            Positioned(
              top: screenSize.height / 2 - 20,
              left: 40,
              child: FocusTraversalOrder(
                order: const NumericFocusOrder(_kTabChevronPrev),
                child: IconButton(
                  icon: Transform(
                    alignment: Alignment.center,
                    transform: Matrix4.rotationY(math.pi),
                    child: Image.asset('assets/images/chevron_right.png', height: 40),
                  ),
                  onPressed: () {
                    if (context.canPop()) {
                      context.pop();
                    } else {
                      context.go(widget.previousRoute);
                    }
                  },
                  tooltip: 'Précédent',
                ),
              ),
            ),
            Positioned(
              top: screenSize.height / 2 - 20,
              right: 40,
              child: FocusTraversalOrder(
                order: const NumericFocusOrder(_kTabChevronNext),
                child: IconButton(
                  icon: Image.asset('assets/images/chevron_right.png', height: 40),
                  onPressed: _submitForm,
                  tooltip: 'Suivant',
                ),
              ),
            ),
          ],
        ],
        ),
      ),
    );
  }

  Widget _buildCard(BuildContext context, DisplayConfig config, Size screenSize) {
    // Si mode Readonly Desktop : Layout spécial "Vintage" horizontal
    if (config.isReadonly && !config.isMobile && widget.embedContentOnly) {
      return _buildReadonlyDesktopCard(context, config, screenSize);
    }

    // Si mode Readonly Mobile : Layout spécial "Vintage" vertical
    if (config.isReadonly && config.isMobile && widget.embedContentOnly) {
      return Padding(
        padding: EdgeInsets.symmetric(horizontal: screenSize.width * 0.05),
        child: _buildMobileReadonlyCard(context, config, screenSize),
      );
    }

    return Stack(
      clipBehavior: Clip.none,
      children: [
        Container(
          width: config.isMobile ? screenSize.width * 0.9 : screenSize.width * 0.6,
          padding: EdgeInsets.symmetric(
            vertical: config.isMobile ? 20 : (config.isReadonly ? 24 : 28),
            horizontal: config.isMobile ? 24 : 50,
          ),
          decoration: BoxDecoration(
            image: DecorationImage(
              image: AssetImage(
                config.isMobile
                    ? _getVerticalCardAsset()
                    : widget.cardColor.path
              ),
              fit: BoxFit.fill,
            ),
          ),
          child: Form(
            key: _formKey,
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                if (widget.embedContentOnly) ...[
                  Text(
                    widget.title,
                    style: GoogleFonts.merienda(
                      fontSize: config.isMobile ? 18 : 22,
                      fontWeight: FontWeight.bold,
                      color: Colors.black87,
                    ),
                    textAlign: TextAlign.center,
                  ),
                  SizedBox(height: config.isMobile ? 20.0 : 14.0),
                ],
                config.isMobile
                    ? _buildMobileFields(context, config)
                    : _buildDesktopFields(context, config),
              ],
            ),
          ),
        ),
        if (config.isReadonly && widget.onEdit != null)
          Positioned(
            top: 10,
            right: 10,
            child: IconButton(
              icon: const Icon(Icons.edit, color: Colors.black54),
              onPressed: widget.onEdit,
              tooltip: 'Modifier',
            ),
          ),
      ],
    );
  }

  /// Carte en mode readonly MOBILE avec hauteur adaptative
  Widget _buildMobileReadonlyCard(BuildContext context, DisplayConfig config, Size screenSize) {
    return Container(
      width: double.infinity,
      // Pas de height fixe
      padding: const EdgeInsets.symmetric(vertical: 20.0, horizontal: 24.0),
      decoration: BoxDecoration(
        image: DecorationImage(
          image: AssetImage(_getVerticalCardAsset()),
          fit: BoxFit.fill, // Fill pour s'adapter
        ),
        borderRadius: BorderRadius.circular(15),
      ),
      child: Stack(
        children: [
          Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              // Titre + Edit Button
              Row(
                children: [
                  Expanded(
                    child: Text(
                      widget.title,
                      style: GoogleFonts.merienda(
                        fontSize: 18,
                        fontWeight: FontWeight.bold,
                        color: Colors.black87,
                      ),
                      textAlign: TextAlign.center,
                    ),
                  ),
                  if (widget.onEdit != null)
                    const SizedBox(width: 28),
                ],
              ),
              
              // Contenu aligné en haut
              Padding(
                padding: const EdgeInsets.only(top: 20.0),
                child: _buildMobileFields(context, config),
              ),
            ],
          ),
          
          if (widget.onEdit != null)
            Positioned(
              top: 0,
              right: 0,
              child: IconButton(
                padding: EdgeInsets.zero,
                constraints: const BoxConstraints(),
                icon: const Icon(Icons.edit, color: Colors.black54, size: 24),
                onPressed: widget.onEdit,
                tooltip: 'Modifier',
              ),
            ),
        ],
      ),
    );
  }

  /// Carte en mode readonly desktop avec AspectRatio 2:1
  Widget _buildReadonlyDesktopCard(BuildContext context, DisplayConfig config, Size screenSize) {
    final cardWidth = screenSize.width / 2.0;

    return SizedBox(
      width: cardWidth,
      child: AspectRatio(
        aspectRatio: 2.0,
        child: Container(
          padding: const EdgeInsets.symmetric(vertical: 20.0, horizontal: 25.0),
          decoration: BoxDecoration(
            image: DecorationImage(
              image: AssetImage(widget.cardColor.path),
              fit: BoxFit.cover,
            ),
            borderRadius: BorderRadius.circular(15),
          ),
          child: Column(
            children: [
              // Titre + Edit Button
              Row(
                children: [
                  Expanded(
                    child: Text(
                      widget.title,
                      style: GoogleFonts.merienda(fontSize: 22, fontWeight: FontWeight.bold, color: Colors.black87),
                      textAlign: TextAlign.center,
                    ),
                  ),
                  if (widget.onEdit != null)
                    IconButton(
                      icon: const Icon(Icons.edit, color: Colors.black54, size: 28),
                      onPressed: widget.onEdit,
                      tooltip: 'Modifier',
                    ),
                ],
              ),
              const SizedBox(height: 10),
              
              // Contenu
              Expanded(
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    // PHOTO (1/3)
                    Expanded(
                      flex: 1,
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          AspectRatio(
                            aspectRatio: 1,
                            child: LayoutBuilder(
                              builder: (context, constraints) {
                                final side = constraints.biggest.shortestSide;
                                return RegistrationPhotoSlot(
                                  side: side,
                                  imageBytes: _photoBytes,
                                  imageFile: _photoFile,
                                  imagePathOrAsset: _photoPathFramework,
                                  baseShadowColor: Colors.green.shade300,
                                );
                              },
                            ),
                          ),
                          const SizedBox(height: 5),
                          AppCustomCheckbox(
                            label: 'J\'accepte l\'utilisation\nde ma photo.',
                            value: _photoConsent,
                            onChanged: (_) {}, // Readonly
                            checkboxSize: 22.0,
                            fontSize: 14.0,
                          ),
                        ],
                      ),
                    ),
                    const SizedBox(width: 24),
                    
                    // CHAMPS (2/3) - Layout optimisé compact
                    Expanded(
                      flex: 2,
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          // Ligne 1 : Date de naissance + Ville
                          Row(
                            children: [
                              Expanded(flex: 2, child: _buildReadonlyField('Date de naissance', _dateOfBirthController.text)),
                              const SizedBox(width: 16),
                              Expanded(flex: 3, child: _buildReadonlyField('Ville de naissance', _birthCityController.text)),
                            ],
                          ),
                          const SizedBox(height: 5),
                          
                          // Ligne 2 : Pays + NIR
                          Row(
                            children: [
                              Expanded(flex: 2, child: _buildReadonlyField('Pays de naissance', _birthCountryController.text)),
                              const SizedBox(width: 16),
                              Expanded(flex: 3, child: _buildReadonlyField('NIR', _formatNirForDisplay(_nirController.text))),
                            ],
                          ),
                          const SizedBox(height: 5),
                          
                          // Ligne 3 : N° agrément + Date d'obtention
                          Row(
                            children: [
                              Expanded(
                                flex: 3,
                                child: _buildReadonlyField('N° d\'agrément', _agrementController.text),
                              ),
                              const SizedBox(width: 16),
                              Expanded(
                                flex: 2,
                                child: _buildReadonlyField(
                                  'Date d\'obtention de l\'agrément',
                                  _agreementDateController.text.isNotEmpty ? _agreementDateController.text : '—',
                                ),
                              ),
                            ],
                          ),
                          const SizedBox(height: 5),
                          Row(
                            children: [
                              Expanded(
                                child: _buildReadonlyField('Capacité d\'accueil', _capacityController.text),
                              ),
                              const SizedBox(width: 16),
                              Expanded(
                                child: _buildReadonlyField(
                                  'Places disponibles',
                                  _placesAvailableController.text,
                                ),
                              ),
                            ],
                          ),
                        ],
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  /// NIR formaté pour affichage (1 12 34 56 789 012 - 34 ou 2A pour la Corse).
  String _formatNirForDisplay(String value) {
    final raw = nirToRaw(value);
    return raw.length == 15 ? formatNir(raw) : value;
  }

  /// Helper pour champ Readonly style "Beige"
  Widget _buildReadonlyField(String label, String value) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          label, 
          style: GoogleFonts.merienda(fontSize: 16.0, fontWeight: FontWeight.w600),
          overflow: TextOverflow.ellipsis,
        ),
        const SizedBox(height: 3),
        Container(
          width: double.infinity,
          height: 45.0, // Hauteur réduite pour compacter
          padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 10.0),
          decoration: BoxDecoration(
            image: const DecorationImage(
              image: AssetImage('assets/images/bg_beige.png'),
              fit: BoxFit.fill,
            ),
            borderRadius: BorderRadius.circular(8),
          ),
          child: Text(
            value.isNotEmpty ? value : '-',
            style: GoogleFonts.merienda(fontSize: 14.0),
            overflow: TextOverflow.ellipsis,
          ),
        ),
      ],
    );
  }

  /// Layout DESKTOP : Photo à gauche, champs à droite
  Widget _buildDesktopFields(BuildContext context, DisplayConfig config) {
    final double verticalSpacing = config.isReadonly ? 8.0 : 14.0;

    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // Photo + Checkbox à gauche
            SizedBox(
              width: 300,
              child: _buildPhotoSection(context, config),
            ),
            const SizedBox(width: 22),
            // Champs à droite
            Expanded(
              child: Column(
                children: [
                  _buildField(
                    config: config,
                    label: 'Date de naissance',
                    controller: _dateOfBirthController,
                    hint: 'JJ/MM/AAAA',
                    readOnly: true,
                    onTap: () => _selectDate(context),
                    suffixIcon: Icons.calendar_today,
                    validator: (v) => _selectedDate == null ? 'Date requise' : null,
                    focusTraversalOrder: _kTabDateBirth,
                  ),
                  SizedBox(height: verticalSpacing),
                  _buildField(
                    config: config,
                    label: 'Ville de naissance',
                    controller: _birthCityController,
                    hint: 'Ex. Ajaccio, Paris, Casablanca…',
                    validator: _validateBirthCity,
                    focusNode: _birthCityFocus,
                    focusTraversalOrder: _kTabBirthCity,
                  ),
                  SizedBox(height: verticalSpacing),
                  _buildField(
                    config: config,
                    label: 'Pays de naissance',
                    controller: _birthCountryController,
                    hint: 'Ex. France, Maroc…',
                    validator: _validateBirthCountry,
                    focusNode: _birthCountryFocus,
                    focusTraversalOrder: _kTabBirthCountry,
                    textInputAction: TextInputAction.next,
                    onFieldSubmitted: (_) => _nirFocus?.requestFocus(),
                    onEditingComplete: () => _nirFocus?.requestFocus(),
                  ),
                ],
              ),
            ),
          ],
        ),
        SizedBox(height: verticalSpacing),
        NirTextField(
          controller: _nirController,
          focusNode: _nirFocus,
          focusTraversalOrder: _nirFocus != null ? _kTabNir : null,
          fieldWidth: double.infinity,
          fieldHeight: config.isMobile ? 45.0 : 53.0,
          labelFontSize: config.isMobile ? 15.0 : 20.0,
          inputFontSize: config.isMobile ? 14.0 : 18.0,
          labelFieldSpacing: config.isMobile ? 6.0 : 3.0,
        ),
        SizedBox(height: verticalSpacing),
        Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Expanded(
              child: _buildField(
                config: config,
                label: 'N° d\'agrément',
                controller: _agrementController,
                hint: 'Votre numéro d\'agrément',
                validator: (v) => v!.isEmpty ? 'Agrément requis' : null,
                focusTraversalOrder: _kTabAgrement,
              ),
            ),
            const SizedBox(width: 14),
            Expanded(
              child: _buildField(
                config: config,
                label: 'Date d\'obtention de l\'agrément',
                controller: _agreementDateController,
                hint: 'JJ/MM/AAAA',
                readOnly: true,
                onTap: () => _selectAgreementDate(context),
                suffixIcon: Icons.calendar_today,
                validator: (_) =>
                    _selectedAgreementDate == null ? 'Date d\'obtention requise' : null,
                focusTraversalOrder: _kTabAgreementDate,
              ),
            ),
          ],
        ),
        SizedBox(height: verticalSpacing),
        Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Expanded(
              child: _buildField(
                config: config,
                label: 'Capacité d\'accueil',
                controller: _capacityController,
                hint: 'De 1 à $kAmCapaciteAccueilMax enfants',
                keyboardType: TextInputType.number,
                validator: (v) {
                  if (v == null || v.isEmpty) return 'Capacité requise';
                  final n = int.tryParse(v);
                  if (n == null || n < 1) {
                    return 'Entrez un nombre entre 1 et $kAmCapaciteAccueilMax';
                  }
                  if (n > kAmCapaciteAccueilMax) {
                    return 'Maximum $kAmCapaciteAccueilMax';
                  }
                  return null;
                },
                focusTraversalOrder: _kTabCapacity,
              ),
            ),
            const SizedBox(width: 14),
            Expanded(
              child: _buildField(
                config: config,
                label: 'Places disponibles',
                controller: _placesAvailableController,
                hint: 'Entre 0 et la capacité',
                keyboardType: TextInputType.number,
                validator: _validatePlacesAvailable,
                focusTraversalOrder: _kTabPlaces,
              ),
            ),
          ],
        ),
      ],
    );
  }

  /// Layout MOBILE : Tout empilé verticalement
  Widget _buildMobileFields(BuildContext context, DisplayConfig config) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        // Photo + Checkbox en premier
        _buildPhotoSection(context, config),
        const SizedBox(height: 20),
        
        _buildField(
          config: config,
          label: 'Date de naissance',
          controller: _dateOfBirthController,
          hint: 'JJ/MM/AAAA',
          readOnly: true,
          onTap: () => _selectDate(context),
          suffixIcon: Icons.calendar_today,
          validator: (v) => _selectedDate == null ? 'Date requise' : null,
          focusTraversalOrder: _kTabDateBirth,
        ),
        const SizedBox(height: 12),
        
        _buildField(
          config: config,
          label: 'Ville de naissance',
          controller: _birthCityController,
          hint: 'Ex. Ajaccio, Paris, Casablanca…',
          validator: _validateBirthCity,
          focusNode: _birthCityFocus,
          focusTraversalOrder: _kTabBirthCity,
        ),
        const SizedBox(height: 12),
        
        _buildField(
          config: config,
          label: 'Pays de naissance',
          controller: _birthCountryController,
          hint: 'Ex. France, Maroc…',
          validator: _validateBirthCountry,
          focusNode: _birthCountryFocus,
          focusTraversalOrder: _kTabBirthCountry,
          textInputAction: TextInputAction.next,
          onFieldSubmitted: (_) => _nirFocus?.requestFocus(),
          onEditingComplete: () => _nirFocus?.requestFocus(),
        ),
        const SizedBox(height: 12),
        
        NirTextField(
          controller: _nirController,
          focusNode: _nirFocus,
          focusTraversalOrder: _nirFocus != null ? _kTabNir : null,
          fieldWidth: double.infinity,
          fieldHeight: 45.0,
          labelFontSize: 15.0,
          inputFontSize: 14.0,
        ),
        const SizedBox(height: 12),
        
        _buildField(
          config: config,
          label: 'N° d\'agrément',
          controller: _agrementController,
          hint: 'Votre numéro d\'agrément',
          validator: (v) => v!.isEmpty ? 'Agrément requis' : null,
          focusTraversalOrder: _kTabAgrement,
        ),
        const SizedBox(height: 12),
        _buildField(
          config: config,
          label: 'Date d\'obtention de l\'agrément',
          controller: _agreementDateController,
          hint: 'JJ/MM/AAAA',
          readOnly: true,
          onTap: () => _selectAgreementDate(context),
          suffixIcon: Icons.calendar_today,
          validator: (_) =>
              _selectedAgreementDate == null ? 'Date d\'obtention requise' : null,
          focusTraversalOrder: _kTabAgreementDate,
        ),
        const SizedBox(height: 12),
        _buildField(
          config: config,
          label: 'Capacité d\'accueil',
          controller: _capacityController,
          hint: 'De 1 à $kAmCapaciteAccueilMax enfants',
          keyboardType: TextInputType.number,
          validator: (v) {
            if (v == null || v.isEmpty) return 'Capacité requise';
            final n = int.tryParse(v);
            if (n == null || n < 1) {
              return 'Entrez un nombre entre 1 et $kAmCapaciteAccueilMax';
            }
            if (n > kAmCapaciteAccueilMax) {
              return 'Maximum $kAmCapaciteAccueilMax';
            }
            return null;
          },
          focusTraversalOrder: _kTabCapacity,
        ),
        const SizedBox(height: 12),
        _buildField(
          config: config,
          label: 'Places disponibles',
          controller: _placesAvailableController,
          hint: 'Entre 0 et la capacité',
          keyboardType: TextInputType.number,
          validator: _validatePlacesAvailable,
          focusTraversalOrder: _kTabPlaces,
        ),
      ],
    );
  }

  /// Section photo + checkbox (même logique visuelle que les enfants : cadre, croix).
  Widget _buildPhotoSection(BuildContext context, DisplayConfig config) {
    final photoSize = config.isMobile ? 200.0 : 270.0;
    final scaleFactor = config.isMobile ? 0.9 : 1.1;

    final slot = RegistrationPhotoSlot(
      side: photoSize,
      scaleFactor: scaleFactor,
      imageBytes: _photoBytes,
      imageFile: _photoFile,
      imagePathOrAsset: _photoPathFramework,
      onTapPick: config.isReadonly ? null : _pickPhoto,
      onClear: config.isReadonly ? null : _clearRegistrationPhoto,
      baseShadowColor: Colors.green.shade300,
      isMobile: config.isMobile,
    );

    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        if (config.isReadonly)
          slot
        else
          FocusTraversalOrder(
            order: const NumericFocusOrder(_kTabPhotoPick),
            child: slot,
          ),
        SizedBox(height: config.isMobile ? 10.0 : 6.0),
        AppCustomCheckbox(
          label: 'J\'accepte l\'utilisation\nde ma photo.',
          value: _photoConsent,
          onChanged: (val) {
            if (config.isReadonly) return;
            setState(() => _photoConsent = val == true);
          },
        ),
      ],
    );
  }

  /// Construit un champ individuel
  Widget _buildField({
    required DisplayConfig config,
    required String label,
    required TextEditingController controller,
    String? hint,
    TextInputType? keyboardType,
    bool readOnly = false,
    VoidCallback? onTap,
    IconData? suffixIcon,
    String? Function(String?)? validator,
    List<TextInputFormatter>? inputFormatters,
    FocusNode? focusNode,
    double? focusTraversalOrder,
    TextInputAction? textInputAction,
    ValueChanged<String>? onFieldSubmitted,
    VoidCallback? onEditingComplete,
  }) {
    if (config.isReadonly) {
      return FormFieldWrapper(
        config: config,
        label: label,
        value: controller.text,
      );
    } else {
      final field = CustomAppTextField(
        controller: controller,
        focusNode: focusNode,
        labelText: label,
        hintText: hint ?? label,
        fieldWidth: double.infinity,
        fieldHeight: config.isMobile ? 45.0 : 53.0,
        labelFontSize: config.isMobile ? 15.0 : 20.0,
        inputFontSize: config.isMobile ? 14.0 : 18.0,
        labelFieldSpacing: config.isMobile ? 6.0 : 3.0,
        keyboardType: keyboardType ?? TextInputType.text,
        readOnly: readOnly,
        onTap: onTap,
        suffixIcon: suffixIcon,
        validator: validator,
        inputFormatters: inputFormatters,
        textInputAction: textInputAction,
        onFieldSubmitted: onFieldSubmitted,
        onEditingComplete: onEditingComplete,
      );
      final o = focusTraversalOrder;
      if (o != null) {
        return FocusTraversalOrder(
          order: NumericFocusOrder(o),
          child: field,
        );
      }
      return field;
    }
  }

  /// Boutons mobile
  Widget _buildMobileButtons(BuildContext context, DisplayConfig config, Size screenSize) {
    return Padding(
      padding: EdgeInsets.symmetric(
        horizontal: screenSize.width * 0.05,
      ),
      child: Row(
        children: [
          Expanded(
            child: HoverReliefWidget(
              child: CustomNavigationButton(
                text: 'Précédent',
                style: NavigationButtonStyle.purple,
                onPressed: () {
                  if (context.canPop()) {
                    context.pop();
                  } else {
                    context.go(widget.previousRoute);
                  }
                },
                width: double.infinity,
                height: 50,
                fontSize: 16,
              ),
            ),
          ),
          const SizedBox(width: 16),
          Expanded(
            child: HoverReliefWidget(
              child: CustomNavigationButton(
                text: 'Suivant',
                style: NavigationButtonStyle.green,
                onPressed: _submitForm,
                width: double.infinity,
                height: 50,
                fontSize: 16,
              ),
            ),
          ),
        ],
      ),
    );
  }

  /// Retourne l'asset de carte vertical correspondant à la couleur
  String _getVerticalCardAsset() {
    switch (widget.cardColor) {
      case CardColorHorizontal.blue:
        return CardColorVertical.blue.path;
      case CardColorHorizontal.green:
        return CardColorVertical.green.path;
      case CardColorHorizontal.lavender:
        return CardColorVertical.lavender.path;
      case CardColorHorizontal.lime:
        return CardColorVertical.lime.path;
      case CardColorHorizontal.peach:
        return CardColorVertical.peach.path;
      case CardColorHorizontal.pink:
        return CardColorVertical.pink.path;
      case CardColorHorizontal.red:
        return CardColorVertical.red.path;
    }
  }
}
