import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:p_tits_pas/models/relais_model.dart';
import 'package:p_tits_pas/utils/phone_utils.dart';
import 'package:p_tits_pas/services/relais_service.dart';

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

  @override
  State<RelaisManagementPanel> createState() => _RelaisManagementPanelState();
}

class _RelaisManagementPanelState extends State<RelaisManagementPanel> {
  bool _isLoading = false;
  String? _error;
  List<RelaisModel> _relais = [];
  String? _hoveredRelaisId;

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

  Future<void> _loadRelais() async {
    setState(() {
      _isLoading = true;
      _error = null;
    });
    try {
      final list = await RelaisService.getRelais();
      if (!mounted) return;
      setState(() {
        _relais = list;
        _isLoading = false;
      });
    } catch (e) {
      if (!mounted) return;
      setState(() {
        _error = e.toString().replaceAll('Exception: ', '');
        _isLoading = false;
      });
    }
  }

  Future<void> _openRelaisForm({RelaisModel? relais}) async {
    final result = await showDialog<_RelaisDialogResult>(
      context: context,
      builder: (context) => _RelaisFormDialog(initial: relais),
    );

    if (result == null) return;
    if (!mounted) return;

    try {
      if (result.action == _RelaisDialogAction.delete) {
        if (relais == null) return;
        final confirmed = await showDialog<bool>(
          context: context,
          builder: (ctx) => AlertDialog(
            title: const Text('Supprimer le relais'),
            content: Text('Confirmer la suppression de "${relais.nom}" ?'),
            actions: [
              TextButton(
                onPressed: () => Navigator.of(ctx).pop(false),
                child: const Text('Annuler'),
              ),
              FilledButton(
                onPressed: () => Navigator.of(ctx).pop(true),
                style: FilledButton.styleFrom(
                  backgroundColor: Colors.red.shade700,
                ),
                child: const Text('Supprimer'),
              ),
            ],
          ),
        );

        if (confirmed != true) return;
        await RelaisService.deleteRelais(relais.id);
      } else if (relais == null) {
        await RelaisService.createRelais(result.payload!);
      } else {
        await RelaisService.updateRelais(relais.id, result.payload!);
      }
      if (!mounted) return;
      await _loadRelais();
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text(
            result.action == _RelaisDialogAction.delete
                ? 'Relais supprimé.'
                : (relais == null ? 'Relais créé.' : 'Relais mis à jour.'),
          ),
        ),
      );
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text(
            e.toString().replaceAll('Exception: ', ''),
          ),
          backgroundColor: Colors.red.shade600,
        ),
      );
    }
  }

  String _horairesSummary(Map<String, dynamic>? horaires) {
    if (horaires == null || horaires.isEmpty) {
      return 'Horaires non renseignés';
    }
    final actifs = horaires.entries.where((entry) {
      final value = entry.value;
      if (value is Map<String, dynamic>) {
        final ferme = value['ferme'] == true;
        if (ferme) return false;
        final matinOuverture = value['matin_ouverture']?.toString() ?? '';
        final matinFermeture = value['matin_fermeture']?.toString() ?? '';
        final soirOuverture = value['soir_ouverture']?.toString() ?? '';
        final soirFermeture = value['soir_fermeture']?.toString() ?? '';
        final matinOuvert =
            matinOuverture.isNotEmpty && matinFermeture.isNotEmpty;
        final soirOuvert = soirOuverture.isNotEmpty && soirFermeture.isNotEmpty;
        return matinOuvert || soirOuvert;
      }
      return false;
    }).length;
    return '$actifs jour(s) ouvert(s)';
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(24),
      child: Center(
        child: ConstrainedBox(
          constraints: const BoxConstraints(maxWidth: 720),
          child: Card(
            elevation: 2,
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(12),
            ),
            child: Padding(
              padding: const EdgeInsets.all(24),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  Row(
                    children: [
                      const Icon(
                        Icons.location_city_outlined,
                        size: 22,
                        color: Color(0xFF9CC5C0),
                      ),
                      const SizedBox(width: 10),
                      Text(
                        'Gestion des relais',
                        style:
                            Theme.of(context).textTheme.titleMedium?.copyWith(
                                  fontWeight: FontWeight.bold,
                                  color: const Color(0xFF2D6A4F),
                                ),
                      ),
                      const Spacer(),
                      ElevatedButton.icon(
                        onPressed: () => _openRelaisForm(),
                        icon: const Icon(Icons.add),
                        label: const Text('Ajouter un relais'),
                      ),
                    ],
                  ),
                  const SizedBox(height: 16),
                  Container(
                    height: 390,
                    padding: const EdgeInsets.all(10),
                    decoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.circular(10),
                      border: Border.all(color: Colors.black12),
                    ),
                    child: _isLoading
                        ? const Center(child: CircularProgressIndicator())
                        : _error != null
                            ? Center(
                                child: Text(
                                  _error!,
                                  style: TextStyle(color: Colors.red.shade700),
                                ),
                              )
                            : _relais.isEmpty
                                ? const Center(
                                    child: Text('Aucun relais configuré.'),
                                  )
                                : ListView.separated(
                                    itemCount: _relais.length,
                                    separatorBuilder: (_, __) =>
                                        const SizedBox(height: 10),
                                    itemBuilder: (context, index) {
                                      final relais = _relais[index];
                                      final isInactive = !relais.actif;
                                      final isHovered =
                                          _hoveredRelaisId == relais.id;
                                      final subtitle = [
                                        relais.adresse,
                                        if (relais.ligneFixe?.isNotEmpty ==
                                            true)
                                          'Ligne fixe : ${relais.ligneFixe}',
                                        _horairesSummary(
                                            relais.horairesOuverture),
                                        'Statut : ${relais.actif ? 'Actif' : 'Inactif'}',
                                        if (relais.notes?.isNotEmpty == true)
                                          'Notes : ${relais.notes}',
                                      ];

                                      return MouseRegion(
                                        onEnter: (_) => setState(
                                          () => _hoveredRelaisId = relais.id,
                                        ),
                                        onExit: (_) => setState(
                                          () => _hoveredRelaisId = null,
                                        ),
                                        child: Card(
                                          color: isInactive
                                              ? const Color(0xFFFFF4F4)
                                              : null,
                                          shape: RoundedRectangleBorder(
                                            borderRadius:
                                                BorderRadius.circular(10),
                                            side: BorderSide(
                                              color: isInactive
                                                  ? const Color(0xFFFFD0D0)
                                                  : Colors.transparent,
                                            ),
                                          ),
                                          child: Padding(
                                            padding: const EdgeInsets.symmetric(
                                              horizontal: 12,
                                              vertical: 10,
                                            ),
                                            child: Row(
                                              children: [
                                                const Icon(
                                                  Icons.location_city_outlined,
                                                ),
                                                const SizedBox(width: 12),
                                                Expanded(
                                                  child: Column(
                                                    crossAxisAlignment:
                                                        CrossAxisAlignment
                                                            .start,
                                                    children: [
                                                      Text(
                                                        relais.nom,
                                                        style: TextStyle(
                                                          fontWeight:
                                                              FontWeight.w600,
                                                          color: isInactive
                                                              ? const Color(
                                                                  0xFF8A3A3A)
                                                              : null,
                                                        ),
                                                      ),
                                                      const SizedBox(height: 2),
                                                      Text(
                                                        subtitle
                                                            .join('   •   '),
                                                        maxLines: 2,
                                                        overflow: TextOverflow
                                                            .ellipsis,
                                                        style: const TextStyle(
                                                          color: Colors.black54,
                                                          fontSize: 12,
                                                        ),
                                                      ),
                                                    ],
                                                  ),
                                                ),
                                                SizedBox(
                                                  width: 36,
                                                  child: AnimatedOpacity(
                                                    duration: const Duration(
                                                      milliseconds: 120,
                                                    ),
                                                    opacity: isHovered ? 1 : 0,
                                                    child: IgnorePointer(
                                                      ignoring: !isHovered,
                                                      child: IconButton(
                                                        onPressed: () =>
                                                            _openRelaisForm(
                                                                relais: relais),
                                                        icon: const Icon(
                                                            Icons.edit),
                                                        tooltip: 'Modifier',
                                                      ),
                                                    ),
                                                  ),
                                                ),
                                              ],
                                            ),
                                          ),
                                        ),
                                      );
                                    },
                                  ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

class _RelaisFormDialog extends StatefulWidget {
  final RelaisModel? initial;

  const _RelaisFormDialog({required this.initial});

  @override
  State<_RelaisFormDialog> createState() => _RelaisFormDialogState();
}

class _RelaisFormDialogState extends State<_RelaisFormDialog> {
  static const double _targetTimeFieldWidth = 112;
  static const double _minTimeFieldWidth = 96;
  static const double _gap = 8;
  static const double _dayLabelWidth = 70;
  static const double _closedAreaWidth = 86;
  static const double _separatorLineWidth = 1;
  static const double _groupSeparatorWidth = (_gap * 2) + _separatorLineWidth;
  static const double _modalInnerPadding = 16;
  static const double _modalHorizontalSafetyMargin = 24;

  late final TextEditingController _nomCtrl;
  late final TextEditingController _streetCtrl;
  late final TextEditingController _postalCodeCtrl;
  late final TextEditingController _cityCtrl;
  late final TextEditingController _ligneFixeCtrl;
  late final TextEditingController _notesCtrl;
  final Map<String, TextEditingController> _morningOpenCtrls = {};
  final Map<String, TextEditingController> _morningCloseCtrls = {};
  final Map<String, TextEditingController> _eveningOpenCtrls = {};
  final Map<String, TextEditingController> _eveningCloseCtrls = {};
  final Map<String, bool> _closedByDay = {};
  bool _actif = true;

  static const List<String> _days = [
    'lundi',
    'mardi',
    'mercredi',
    'jeudi',
    'vendredi',
    'samedi',
    'dimanche',
  ];

  @override
  void initState() {
    super.initState();
    final initial = widget.initial;
    _nomCtrl = TextEditingController(text: initial?.nom ?? '');
    final addressParts = _splitAddress(initial?.adresse);
    _streetCtrl = TextEditingController(text: addressParts.street);
    _postalCodeCtrl = TextEditingController(text: addressParts.postalCode);
    _cityCtrl = TextEditingController(text: addressParts.city);
    _ligneFixeCtrl = TextEditingController(text: initial?.ligneFixe ?? '');
    _notesCtrl = TextEditingController(text: initial?.notes ?? '');
    _actif = initial?.actif ?? true;

    final horaires = initial?.horairesOuverture ?? <String, dynamic>{};
    for (final day in _days) {
      final value = horaires[day];
      String matinOuverture = '';
      String matinFermeture = '';
      String soirOuverture = '';
      String soirFermeture = '';
      bool ferme = false;

      if (value is Map<String, dynamic>) {
        matinOuverture = _normalizeTime(
          value['matin_ouverture']?.toString() ??
              value['ouverture']?.toString(),
        );
        matinFermeture = _normalizeTime(
          value['matin_fermeture']?.toString() ??
              value['fermeture']?.toString(),
        );
        soirOuverture = _normalizeTime(value['soir_ouverture']?.toString());
        soirFermeture = _normalizeTime(value['soir_fermeture']?.toString());
        ferme = value['ferme'] == true;
      } else if (value is String && value.contains('-')) {
        final parts = value.split('-');
        if (parts.length == 2) {
          matinOuverture = _normalizeTime(parts[0].trim());
          matinFermeture = _normalizeTime(parts[1].trim());
        }
      }

      _morningOpenCtrls[day] = TextEditingController(text: matinOuverture);
      _morningCloseCtrls[day] = TextEditingController(text: matinFermeture);
      _eveningOpenCtrls[day] = TextEditingController(text: soirOuverture);
      _eveningCloseCtrls[day] = TextEditingController(text: soirFermeture);
      final isWeekend = day == 'samedi' || day == 'dimanche';
      _closedByDay[day] = widget.initial == null ? isWeekend : ferme;
    }
  }

  @override
  void dispose() {
    _nomCtrl.dispose();
    _streetCtrl.dispose();
    _postalCodeCtrl.dispose();
    _cityCtrl.dispose();
    _ligneFixeCtrl.dispose();
    _notesCtrl.dispose();
    for (final c in _morningOpenCtrls.values) {
      c.dispose();
    }
    for (final c in _morningCloseCtrls.values) {
      c.dispose();
    }
    for (final c in _eveningOpenCtrls.values) {
      c.dispose();
    }
    for (final c in _eveningCloseCtrls.values) {
      c.dispose();
    }
    super.dispose();
  }

  Map<String, dynamic> _buildPayload() {
    final horaires = <String, dynamic>{};
    for (final day in _days) {
      final ferme = _closedByDay[day] ?? false;
      final matinOuverture = _morningOpenCtrls[day]!.text.trim();
      final matinFermeture = _morningCloseCtrls[day]!.text.trim();
      final soirOuverture = _eveningOpenCtrls[day]!.text.trim();
      final soirFermeture = _eveningCloseCtrls[day]!.text.trim();

      horaires[day] = <String, dynamic>{
        'matin_ouverture': matinOuverture,
        'matin_fermeture': matinFermeture,
        'soir_ouverture': soirOuverture,
        'soir_fermeture': soirFermeture,
        'ferme': ferme,
      };
    }

    final payload = <String, dynamic>{
      'nom': _nomCtrl.text.trim(),
      'adresse': _composeAddress(),
      'actif': _actif,
      'horaires_ouverture': horaires,
    };

    final ligneFixe = _ligneFixeCtrl.text.trim();
    if (ligneFixe.isNotEmpty) {
      payload['ligne_fixe'] = ligneFixe;
    }

    final notes = _notesCtrl.text.trim();
    if (notes.isNotEmpty) {
      payload['notes'] = notes;
    }

    return payload;
  }

  bool _isValid() {
    if (_nomCtrl.text.trim().isEmpty) {
      return false;
    }
    if (_streetCtrl.text.trim().isEmpty || _cityCtrl.text.trim().isEmpty) {
      return false;
    }
    if (!_isValidPostalCode(_postalCodeCtrl.text.trim())) {
      return false;
    }
    if (validateFrenchNationalPhone(_ligneFixeCtrl.text, allowEmpty: true) != null) {
      return false;
    }

    for (final day in _days) {
      final ferme = _closedByDay[day] ?? false;
      if (ferme) continue;

      final matinOuverture = _morningOpenCtrls[day]!.text.trim();
      final matinFermeture = _morningCloseCtrls[day]!.text.trim();
      final soirOuverture = _eveningOpenCtrls[day]!.text.trim();
      final soirFermeture = _eveningCloseCtrls[day]!.text.trim();

      if (!_isValidSlot(matinOuverture, matinFermeture) ||
          !_isValidSlot(soirOuverture, soirFermeture)) {
        return false;
      }
    }

    return true;
  }

  bool _isValidSlot(String start, String end) {
    final bothEmpty = start.isEmpty && end.isEmpty;
    if (bothEmpty) return true;
    if (start.isEmpty || end.isEmpty) return false;
    return _isValidTime(start) && _isValidTime(end);
  }

  bool _isValidPostalCode(String value) {
    return RegExp(r'^\d{5}$').hasMatch(value);
  }

  _AddressParts _splitAddress(String? rawAddress) {
    if (rawAddress == null || rawAddress.trim().isEmpty) {
      return const _AddressParts(street: '', postalCode: '', city: '');
    }

    final raw = rawAddress.trim().replaceAll(RegExp(r'\s+'), ' ');
    final postalCityMatch =
        RegExp(r'^(.+?)[,\s]+(\d{5})\s+(.+)$').firstMatch(raw);

    if (postalCityMatch != null) {
      final street = (postalCityMatch.group(1) ?? '')
          .replaceAll(RegExp(r'[,;\s]+$'), '')
          .trim();
      final postalCode = (postalCityMatch.group(2) ?? '').trim();
      final city = (postalCityMatch.group(3) ?? '').trim();
      return _AddressParts(
        street: street,
        postalCode: postalCode,
        city: city,
      );
    }

    return _AddressParts(street: raw, postalCode: '', city: '');
  }

  String _composeAddress() {
    final street = _streetCtrl.text.trim();
    final postalCode = _postalCodeCtrl.text.trim();
    final city = _cityCtrl.text.trim();
    if (postalCode.isEmpty && city.isEmpty) {
      return street;
    }
    return '$street, $postalCode $city'.trim();
  }

  bool _isValidTime(String value) {
    final match = RegExp(r'^([01]\d|2[0-3]):([0-5]\d)$').firstMatch(value);
    return match != null;
  }

  String _normalizeTime(String? raw) {
    if (raw == null || raw.trim().isEmpty) return '';
    final compact = raw.replaceAll(RegExp(r'\D'), '');
    if (compact.length == 4) {
      return '${compact.substring(0, 2)}:${compact.substring(2, 4)}';
    }
    final trimmed = raw.trim();
    return _isValidTime(trimmed) ? trimmed : '';
  }

  Future<void> _pickTime(TextEditingController controller) async {
    final currentText = controller.text.trim();
    TimeOfDay initial = const TimeOfDay(hour: 9, minute: 0);
    if (_isValidTime(currentText)) {
      final parts = currentText.split(':');
      initial = TimeOfDay(
        hour: int.parse(parts[0]),
        minute: int.parse(parts[1]),
      );
    }

    final picked = await showTimePicker(
      context: context,
      initialTime: initial,
      builder: (context, child) {
        return MediaQuery(
          data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: true),
          child: child ?? const SizedBox.shrink(),
        );
      },
    );

    if (picked == null) return;
    final hh = picked.hour.toString().padLeft(2, '0');
    final mm = picked.minute.toString().padLeft(2, '0');
    setState(() {
      controller.text = '$hh:$mm';
    });
  }

  @override
  Widget build(BuildContext context) {
    final isCreation = widget.initial == null;
    final availableWidth =
        MediaQuery.of(context).size.width - _modalHorizontalSafetyMargin;
    const preferredHoursWidth = _dayLabelWidth +
        ((_targetTimeFieldWidth * 2) + _gap) +
        _groupSeparatorWidth +
        ((_targetTimeFieldWidth * 2) + _gap) +
        _gap +
        _closedAreaWidth;
    const preferredDialogWidth = preferredHoursWidth + (_modalInnerPadding * 2);
    final dialogWidth =
        preferredDialogWidth.clamp(360.0, availableWidth).toDouble();

    return Dialog(
      child: ConstrainedBox(
        constraints: BoxConstraints(
          maxWidth: dialogWidth,
          minWidth: dialogWidth,
          maxHeight: 700,
        ),
        child: Padding(
          padding: const EdgeInsets.all(_modalInnerPadding),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Row(
                children: [
                  Text(
                    isCreation ? 'Nouveau relais' : 'Modifier relais',
                    style: const TextStyle(
                      fontSize: 18,
                      fontWeight: FontWeight.w700,
                    ),
                  ),
                  const Spacer(),
                  if (!isCreation)
                    IconButton(
                      onPressed: () => Navigator.of(context).pop(),
                      icon: const Icon(Icons.close),
                    ),
                ],
              ),
              const SizedBox(height: 8),
              Expanded(
                child: SingleChildScrollView(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: [
                      const SizedBox(height: 6),
                      _buildTechniqueFields(),
                      const SizedBox(height: 16),
                      _buildTerritorialFields(),
                    ],
                  ),
                ),
              ),
              const SizedBox(height: 12),
              Align(
                alignment: Alignment.centerRight,
                child: Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    if (isCreation) ...[
                      TextButton(
                        onPressed: () => Navigator.of(context).pop(),
                        child: const Text('Annuler'),
                      ),
                      const SizedBox(width: 8),
                      FilledButton(
                        onPressed: _isValid()
                            ? () => Navigator.of(context).pop(
                                  _RelaisDialogResult(
                                    action: _RelaisDialogAction.save,
                                    payload: _buildPayload(),
                                  ),
                                )
                            : null,
                        child: const Text('Créer'),
                      ),
                    ] else ...[
                      OutlinedButton(
                        onPressed: () => Navigator.of(context).pop(
                          const _RelaisDialogResult(
                            action: _RelaisDialogAction.delete,
                          ),
                        ),
                        child: const Text('Supprimer'),
                      ),
                      const SizedBox(width: 8),
                      FilledButton(
                        onPressed: _isValid()
                            ? () => Navigator.of(context).pop(
                                  _RelaisDialogResult(
                                    action: _RelaisDialogAction.save,
                                    payload: _buildPayload(),
                                  ),
                                )
                            : null,
                        child: const Text('Modifier'),
                      ),
                    ],
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildTechniqueFields() {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        TextField(
          controller: _nomCtrl,
          onChanged: (_) => setState(() {}),
          decoration: const InputDecoration(
            labelText: 'Nom du relais *',
            border: OutlineInputBorder(),
          ),
        ),
        const SizedBox(height: 12),
        TextField(
          controller: _ligneFixeCtrl,
          keyboardType: TextInputType.phone,
          inputFormatters: frenchPhoneInputFormatters,
          decoration: const InputDecoration(
            labelText: 'Ligne fixe',
            hintText: '01 23 45 67 89',
            border: OutlineInputBorder(),
          ),
        ),
        const SizedBox(height: 12),
        SwitchListTile(
          contentPadding: EdgeInsets.zero,
          title: const Text('Relais actif'),
          value: _actif,
          onChanged: (value) => setState(() => _actif = value),
        ),
      ],
    );
  }

  Widget _buildTerritorialFields() {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        _RelaisAddressFields(
          streetController: _streetCtrl,
          postalCodeController: _postalCodeCtrl,
          cityController: _cityCtrl,
          onChanged: () => setState(() {}),
        ),
        const SizedBox(height: 12),
        TextField(
          controller: _notesCtrl,
          maxLines: 3,
          decoration: const InputDecoration(
            labelText: 'Notes',
            border: OutlineInputBorder(),
          ),
        ),
        const SizedBox(height: 12),
        Align(
          alignment: Alignment.centerLeft,
          child: Text(
            'Horaires hebdomadaires',
            style: TextStyle(
              fontWeight: FontWeight.w600,
              color: Colors.grey.shade800,
            ),
          ),
        ),
        const SizedBox(height: 6),
        LayoutBuilder(
          builder: (context, constraints) {
            final availableHoursWidth = constraints.maxWidth;
            const fixedWidth = _dayLabelWidth +
                _groupSeparatorWidth +
                _gap +
                _closedAreaWidth +
                (_gap * 2);
            final computedTimeFieldWidth =
                ((availableHoursWidth - fixedWidth) / 4)
                    .clamp(_minTimeFieldWidth, _targetTimeFieldWidth)
                    .toDouble();
            final groupWidth = (computedTimeFieldWidth * 2) + _gap;
            final hoursContentWidth = _dayLabelWidth +
                groupWidth +
                _groupSeparatorWidth +
                groupWidth +
                _gap +
                _closedAreaWidth;

            return SizedBox(
              width: hoursContentWidth,
              child: Stack(
                children: [
                  Positioned(
                    left: _dayLabelWidth +
                        groupWidth +
                        (_groupSeparatorWidth / 2),
                    top: 0,
                    bottom: 0,
                    child: Container(
                      width: _separatorLineWidth,
                      color: Colors.grey.shade400,
                    ),
                  ),
                  Column(
                    children: [
                      Row(
                        children: [
                          const SizedBox(width: _dayLabelWidth),
                          SizedBox(
                            width: groupWidth,
                            child: Center(
                              child: Text(
                                'Matin',
                                style: TextStyle(
                                  fontWeight: FontWeight.w600,
                                  color: Colors.grey.shade800,
                                ),
                              ),
                            ),
                          ),
                          const SizedBox(width: _groupSeparatorWidth),
                          SizedBox(
                            width: groupWidth,
                            child: Center(
                              child: Text(
                                'Après-midi',
                                style: TextStyle(
                                  fontWeight: FontWeight.w600,
                                  color: Colors.grey.shade800,
                                ),
                              ),
                            ),
                          ),
                          const SizedBox(width: _closedAreaWidth),
                        ],
                      ),
                      const SizedBox(height: 4),
                      Row(
                        children: [
                          const SizedBox(width: _dayLabelWidth),
                          SizedBox(
                            width: computedTimeFieldWidth,
                            child: const Center(
                              child: Text(
                                'Début',
                                style: TextStyle(fontSize: 12),
                              ),
                            ),
                          ),
                          const SizedBox(width: _gap),
                          SizedBox(
                            width: computedTimeFieldWidth,
                            child: const Center(
                              child: Text(
                                'Fin',
                                style: TextStyle(fontSize: 12),
                              ),
                            ),
                          ),
                          const SizedBox(width: _groupSeparatorWidth),
                          SizedBox(
                            width: computedTimeFieldWidth,
                            child: const Center(
                              child: Text(
                                'Début',
                                style: TextStyle(fontSize: 12),
                              ),
                            ),
                          ),
                          const SizedBox(width: _gap),
                          SizedBox(
                            width: computedTimeFieldWidth,
                            child: const Center(
                              child: Text(
                                'Fin',
                                style: TextStyle(fontSize: 12),
                              ),
                            ),
                          ),
                          const SizedBox(width: _gap),
                          const SizedBox(width: _closedAreaWidth),
                        ],
                      ),
                      const SizedBox(height: 6),
                      ..._days.map((day) {
                        final ferme = _closedByDay[day] ?? false;
                        return Padding(
                          padding: const EdgeInsets.only(bottom: 8),
                          child: Row(
                            children: [
                              SizedBox(
                                width: _dayLabelWidth,
                                child: Text(
                                  '${day[0].toUpperCase()}${day.substring(1)}',
                                  style: const TextStyle(fontSize: 13),
                                ),
                              ),
                              _buildTimeField(
                                controller: _morningOpenCtrls[day]!,
                                enabled: !ferme,
                                placeholder: '. . : . .',
                                width: computedTimeFieldWidth,
                              ),
                              const SizedBox(width: _gap),
                              _buildTimeField(
                                controller: _morningCloseCtrls[day]!,
                                enabled: !ferme,
                                placeholder: '. . : . .',
                                width: computedTimeFieldWidth,
                              ),
                              const SizedBox(width: _groupSeparatorWidth),
                              _buildTimeField(
                                controller: _eveningOpenCtrls[day]!,
                                enabled: !ferme,
                                placeholder: '. . : . .',
                                width: computedTimeFieldWidth,
                              ),
                              const SizedBox(width: _gap),
                              _buildTimeField(
                                controller: _eveningCloseCtrls[day]!,
                                enabled: !ferme,
                                placeholder: '. . : . .',
                                width: computedTimeFieldWidth,
                              ),
                              const SizedBox(width: _gap),
                              Checkbox(
                                value: ferme,
                                onChanged: (value) {
                                  setState(() {
                                    _closedByDay[day] = value ?? false;
                                  });
                                },
                              ),
                              const Text('Fermé'),
                            ],
                          ),
                        );
                      }),
                    ],
                  ),
                ],
              ),
            );
          },
        ),
      ],
    );
  }

  Widget _buildTimeField({
    required TextEditingController controller,
    required bool enabled,
    required String placeholder,
    required double width,
  }) {
    return SizedBox(
      width: width,
      child: TextField(
        controller: controller,
        enabled: enabled,
        onChanged: (_) => setState(() {}),
        keyboardType: TextInputType.number,
        inputFormatters: [
          FilteringTextInputFormatter.digitsOnly,
          LengthLimitingTextInputFormatter(4),
          _HourMinuteFormatter(),
        ],
        decoration: InputDecoration(
          hintText: placeholder,
          border: const OutlineInputBorder(),
          isDense: true,
          suffixIcon: ExcludeFocus(
            child: GestureDetector(
              onTap: enabled ? () => _pickTime(controller) : null,
              child: const Padding(
                padding: EdgeInsets.all(8),
                child: Icon(Icons.schedule, size: 18),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

class _RelaisAddressFields extends StatelessWidget {
  final TextEditingController streetController;
  final TextEditingController postalCodeController;
  final TextEditingController cityController;
  final VoidCallback onChanged;

  const _RelaisAddressFields({
    required this.streetController,
    required this.postalCodeController,
    required this.cityController,
    required this.onChanged,
  });

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        TextField(
          controller: streetController,
          onChanged: (_) => onChanged(),
          keyboardType: TextInputType.streetAddress,
          textCapitalization: TextCapitalization.words,
          autofillHints: const [AutofillHints.fullStreetAddress],
          decoration: const InputDecoration(
            labelText: 'Rue *',
            hintText: 'Numéro et nom de rue',
            border: OutlineInputBorder(),
            prefixIcon: Icon(Icons.location_on_outlined),
          ),
        ),
        const SizedBox(height: 10),
        Row(
          children: [
            SizedBox(
              width: 140,
              child: TextField(
                controller: postalCodeController,
                onChanged: (_) => onChanged(),
                keyboardType: TextInputType.number,
                inputFormatters: [
                  FilteringTextInputFormatter.digitsOnly,
                  LengthLimitingTextInputFormatter(5),
                ],
                decoration: const InputDecoration(
                  labelText: 'Code postal *',
                  hintText: '5 chiffres',
                  border: OutlineInputBorder(),
                ),
              ),
            ),
            const SizedBox(width: 10),
            Expanded(
              child: TextField(
                controller: cityController,
                onChanged: (_) => onChanged(),
                textCapitalization: TextCapitalization.words,
                decoration: const InputDecoration(
                  labelText: 'Ville *',
                  hintText: 'Ville',
                  border: OutlineInputBorder(),
                ),
              ),
            ),
          ],
        ),
      ],
    );
  }
}

class _AddressParts {
  final String street;
  final String postalCode;
  final String city;

  const _AddressParts({
    required this.street,
    required this.postalCode,
    required this.city,
  });
}

enum _RelaisDialogAction { save, delete }

class _RelaisDialogResult {
  final _RelaisDialogAction action;
  final Map<String, dynamic>? payload;

  const _RelaisDialogResult({
    required this.action,
    this.payload,
  });
}

class _HourMinuteFormatter extends TextInputFormatter {
  @override
  TextEditingValue formatEditUpdate(
    TextEditingValue oldValue,
    TextEditingValue newValue,
  ) {
    final digits = newValue.text.replaceAll(RegExp(r'\D'), '');
    final limited = digits.length > 4 ? digits.substring(0, 4) : digits;

    String text;
    if (limited.length <= 2) {
      text = limited;
    } else {
      text = '${limited.substring(0, 2)}:${limited.substring(2)}';
    }

    return TextEditingValue(
      text: text,
      selection: TextSelection.collapsed(offset: text.length),
    );
  }
}
