import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:p_tits_pas/models/dossier_unifie.dart';
import 'package:p_tits_pas/utils/date_display_utils.dart';
import 'package:p_tits_pas/utils/enfant_status_utils.dart';
import 'package:p_tits_pas/services/user_service.dart';
import 'package:p_tits_pas/services/api/api_config.dart';
import 'package:p_tits_pas/widgets/admin/common/validation_detail_section.dart';
import 'package:p_tits_pas/widgets/common/identity_block.dart';
import 'package:p_tits_pas/widgets/common/auth_network_image.dart';
import 'validation_modal_theme.dart';
import 'validation_refus_form.dart';
import 'validation_valider_confirm_dialog.dart';

/// Wizard de validation dossier famille : étapes sobres (label/valeur), récap, Valider/Refuser/Annuler, page refus. Ticket #107.
class ValidationFamilyWizard extends StatefulWidget {
  final DossierFamille dossier;
  final VoidCallback onClose;
  final VoidCallback onSuccess;
  final void Function(int step, int total)? onStepChanged;

  const ValidationFamilyWizard({
    super.key,
    required this.dossier,
    required this.onClose,
    required this.onSuccess,
    this.onStepChanged,
  });

  @override
  State<ValidationFamilyWizard> createState() => _ValidationFamilyWizardState();
}

class _ValidationFamilyWizardState extends State<ValidationFamilyWizard> {
  int _step = 0;
  bool _showRefusForm = false;
  bool _submitting = false;
  final ScrollController _enfantsScrollController = ScrollController();

  /// Même logique que [ParentRegisterStep3Screen] : masque alpha sur les bords (ShaderMask dstIn).
  bool _enfantsIsScrollable = false;
  bool _enfantsFadeLeft = false;
  bool _enfantsFadeRight = false;

  /// Fraction de la largeur du viewport pour le fondu (identique inscription étape 3).
  static const double _enfantsFadeExtent = 0.05;

  int get _stepCount => 4;

  @override
  void initState() {
    super.initState();
    _enfantsScrollController.addListener(_syncEnfantsScrollFades);
    WidgetsBinding.instance.addPostFrameCallback((_) => _emitStep());
  }

  @override
  void dispose() {
    _enfantsScrollController.removeListener(_syncEnfantsScrollFades);
    _enfantsScrollController.dispose();
    super.dispose();
  }

  void _emitStep() => widget.onStepChanged?.call(_step, _stepCount);

  void _syncEnfantsScrollFades() {
    if (!mounted) return;
    if (!_enfantsScrollController.hasClients) {
      if (_enfantsFadeLeft || _enfantsFadeRight || _enfantsIsScrollable) {
        setState(() {
          _enfantsIsScrollable = false;
          _enfantsFadeLeft = false;
          _enfantsFadeRight = false;
        });
      }
      return;
    }
    final p = _enfantsScrollController.position;
    final scrollable = p.maxScrollExtent > 0;
    final left = scrollable &&
        p.pixels > (p.viewportDimension * _enfantsFadeExtent / 2);
    final right = scrollable &&
        p.pixels <
            (p.maxScrollExtent -
                (p.viewportDimension * _enfantsFadeExtent / 2));
    if (scrollable != _enfantsIsScrollable ||
        left != _enfantsFadeLeft ||
        right != _enfantsFadeRight) {
      setState(() {
        _enfantsIsScrollable = scrollable;
        _enfantsFadeLeft = left;
        _enfantsFadeRight = right;
      });
    }
  }

  bool get _isEnAttente => widget.dossier.isEnAttente;

  String? get _firstParentId => widget.dossier.parents.isNotEmpty
      ? widget.dossier.parents.first.id
      : null;

  static String _v(String? s) =>
      (s != null && s.trim().isNotEmpty) ? s.trim() : 'Non défini';

  /// Date de naissance en jour/mois/année (dd/MM/yyyy).
  static String _formatBirthDate(String? s) =>
      formatIsoDateFr(s, ifEmpty: 'Non défini');

  static String _fullPhotoUrl(String? url) => ApiConfig.absoluteMediaUrl(url);

  @override
  Widget build(BuildContext context) {
    if (_showRefusForm) {
      return _buildRefusPage();
    }
    return Padding(
      padding: const EdgeInsets.all(20),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          const SizedBox(height: 4),
          Expanded(child: _buildStepContent()),
          const SizedBox(height: 24),
          _buildNavigation(),
        ],
      ),
    );
  }

  Widget _buildStepContent() {
    final d = widget.dossier;
    switch (_step) {
      case 0:
        return IdentityBlock.readOnlyFromParentDossier(
          d.parents.first,
          title: 'Parent principal',
        );
      case 1:
        return _buildParent2Step();
      case 2:
        return _buildEnfantsStep();
      case 3:
        return _buildPresentationStep();
      default:
        return const SizedBox();
    }
  }

  Widget _buildParent2Step() {
    if (widget.dossier.parents.length < 2) {
      return const Padding(
        padding: EdgeInsets.symmetric(vertical: 12),
        child: Text('Un seul parent pour ce dossier.',
            style: TextStyle(color: Colors.black87)),
      );
    }
    return IdentityBlock.readOnlyFromParentDossier(
      widget.dossier.parents[1],
      title: 'Deuxième parent',
    );
  }

  static const double _idPhotoAspectRatio = 35 / 45;

  Widget _buildEnfantsStep() {
    final enfants = widget.dossier.enfants;
    if (enfants.isEmpty) {
      return const Padding(
        padding: EdgeInsets.symmetric(vertical: 12),
        child: Text('Aucun enfant renseigné.',
            style: TextStyle(color: Colors.black87)),
      );
    }
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        const Text(
          'Enfants',
          style: TextStyle(
              fontSize: 16, fontWeight: FontWeight.w600, color: Colors.black87),
        ),
        const SizedBox(height: 16),
        Expanded(
          child: LayoutBuilder(
            builder: (context, constraints) {
              final cardHeight = constraints.maxHeight;
              // Carte large : 1/3 photo + 2/3 champs (scroll horizontal si plusieurs enfants).
              final cardWidth = (cardHeight * 1.72).clamp(500.0, 700.0);
              return NotificationListener<ScrollMetricsNotification>(
                onNotification: (_) {
                  _syncEnfantsScrollFades();
                  return false;
                },
                child: ShaderMask(
                  blendMode: BlendMode.dstIn,
                  shaderCallback: (Rect bounds) {
                    final stops = <double>[
                      0.0,
                      _enfantsFadeExtent,
                      1.0 - _enfantsFadeExtent,
                      1.0,
                    ];
                    if (!_enfantsIsScrollable) {
                      return LinearGradient(
                        begin: Alignment.centerLeft,
                        end: Alignment.centerRight,
                        colors: const <Color>[
                          Colors.black,
                          Colors.black,
                          Colors.black,
                          Colors.black,
                        ],
                        stops: stops,
                      ).createShader(bounds);
                    }
                    final leftMask =
                        _enfantsFadeLeft ? Colors.transparent : Colors.black;
                    final rightMask =
                        _enfantsFadeRight ? Colors.transparent : Colors.black;
                    return LinearGradient(
                      begin: Alignment.centerLeft,
                      end: Alignment.centerRight,
                      colors: <Color>[
                        leftMask,
                        Colors.black,
                        Colors.black,
                        rightMask,
                      ],
                      stops: stops,
                    ).createShader(bounds);
                  },
                  child: Listener(
                    onPointerSignal: (event) {
                      if (event is PointerScrollEvent &&
                          _enfantsScrollController.hasClients) {
                        final offset = _enfantsScrollController.offset +
                            event.scrollDelta.dy;
                        _enfantsScrollController.jumpTo(offset.clamp(
                          _enfantsScrollController.position.minScrollExtent,
                          _enfantsScrollController.position.maxScrollExtent,
                        ));
                      }
                    },
                    child: ListView.builder(
                      controller: _enfantsScrollController,
                      scrollDirection: Axis.horizontal,
                      itemCount: enfants.length,
                      itemBuilder: (_, i) => Padding(
                        padding: EdgeInsets.only(
                            right: i < enfants.length - 1 ? 16 : 0),
                        child: SizedBox(
                          width: cardWidth,
                          height: cardHeight,
                          child: _buildEnfantCard(enfants[i]),
                        ),
                      ),
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ],
    );
  }

  /// Fond carte enfant : teintes très pastel ; bordure discrète ; accent léger (barre).
  static const Color _enfantCardBoyBg = Color(0xFFF0F7FB);
  static const Color _enfantCardBoyBorder = Color(0xFFE3EDF4);
  static const Color _enfantCardGirlBg = Color(0xFFFCF5F8);
  static const Color _enfantCardGirlBorder = Color(0xFFEAE3E7);

  static const double _enfantCardRadius = 12;

  static List<BoxShadow> _enfantCardShadows() => [
        BoxShadow(
          color: Colors.black.withOpacity(0.06),
          blurRadius: 14,
          offset: const Offset(0, 4),
        ),
      ];

  static BoxDecoration _enfantCardDecoration(String? gender) {
    final g = (gender ?? '').trim().toUpperCase();
    if (g == 'H') {
      return BoxDecoration(
        color: _enfantCardBoyBg,
        borderRadius: BorderRadius.circular(_enfantCardRadius),
        border: Border.all(color: _enfantCardBoyBorder, width: 1),
        boxShadow: _enfantCardShadows(),
      );
    }
    if (g == 'F') {
      return BoxDecoration(
        color: _enfantCardGirlBg,
        borderRadius: BorderRadius.circular(_enfantCardRadius),
        border: Border.all(color: _enfantCardGirlBorder, width: 1),
        boxShadow: _enfantCardShadows(),
      );
    }
    return BoxDecoration(
      color: Colors.grey.shade50,
      borderRadius: BorderRadius.circular(_enfantCardRadius),
      border: Border.all(color: Colors.grey.shade300),
      boxShadow: _enfantCardShadows(),
    );
  }

  /// Carte enfant : prénom pleine largeur, puis ligne photo 1/3 + colonne 2/3 (champs + statut hors TF si besoin).
  Widget _buildEnfantCard(EnfantDossier e) {
    final photoUrl = _fullPhotoUrl(e.photoUrl);
    final columnStatusLabel = _enfantColumnStatusLabel(e);
    return ClipRRect(
      borderRadius: BorderRadius.circular(_enfantCardRadius),
      child: Container(
        decoration: _enfantCardDecoration(e.gender),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Padding(
              padding: const EdgeInsets.fromLTRB(12, 12, 12, 8),
              child: _enfantLabeledField('Prénom', _v(e.firstName)),
            ),
            Expanded(
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  Expanded(
                    flex: 1,
                    child: LayoutBuilder(
                      builder: (context, c) {
                        // Même marge gauche que le bloc « Prénom » (12) ; droite / haut / bas 8.
                        const padL = 12.0;
                        const padR = 8.0;
                        const padV = 8.0;
                        final maxW =
                            (c.maxWidth - padL - padR).clamp(0.0, double.infinity);
                        final maxH =
                            (c.maxHeight - 2 * padV).clamp(0.0, double.infinity);
                        const ar = _idPhotoAspectRatio;
                        double ph = maxH;
                        double pw = ph * ar;
                        if (pw > maxW) {
                          pw = maxW;
                          ph = pw / ar;
                        }
                        return Padding(
                          padding: const EdgeInsets.fromLTRB(padL, padV, padR, padV),
                          child: Align(
                            alignment: Alignment.centerLeft,
                            child: _buildEnfantPhotoSlot(photoUrl, pw, ph),
                          ),
                        );
                      },
                    ),
                  ),
                  Expanded(
                    flex: 2,
                    child: Padding(
                      padding: const EdgeInsets.fromLTRB(4, 4, 14, 12),
                      child: columnStatusLabel == null
                          ? SingleChildScrollView(
                              child: _buildEnfantInfoFields(e),
                            )
                          : CustomScrollView(
                              slivers: [
                                SliverToBoxAdapter(
                                  child: _buildEnfantInfoFields(e),
                                ),
                                SliverFillRemaining(
                                  hasScrollBody: false,
                                  child: Center(
                                    child: Text(
                                      columnStatusLabel,
                                      textAlign: TextAlign.center,
                                      style: GoogleFonts.merienda(
                                        fontSize: 14,
                                        fontStyle: FontStyle.italic,
                                        fontWeight: FontWeight.w600,
                                        color: Colors.grey.shade800,
                                      ),
                                    ),
                                  ),
                                ),
                              ],
                            ),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  /// Statut dans la colonne 2/3 (scolarisé·e, à naître, sans garde, en garde).
  String? _enfantColumnStatusLabel(EnfantDossier e) {
    return enfantColumnStatusLabel(status: e.status, gender: e.gender);
  }

  /// Nom ; date de naissance et genre sur une ligne (prénom au-dessus, pleine largeur).
  Widget _buildEnfantInfoFields(EnfantDossier e) {
    final isANaitre = (e.status ?? '').trim().toLowerCase() == 'a_naitre';
    final dueDateRenseignee = e.dueDate != null && e.dueDate!.trim().isNotEmpty;
    final dateValue = isANaitre
        ? (dueDateRenseignee ? '${_formatBirthDate(e.dueDate)} (P)' : '– (P)')
        : _formatBirthDate(e.birthDate);

    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        Padding(
          padding: const EdgeInsets.only(bottom: 12),
          child: _enfantLabeledField('Nom', _formatNom(e.lastName)),
        ),
        Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Expanded(
              flex: 3,
              child: _enfantLabeledField('Date de naissance', dateValue),
            ),
            const SizedBox(width: 16),
            Expanded(
              flex: 2,
              child: _enfantLabeledField(
                'Genre',
                _genreEnfantLabel(e.gender, e.status),
              ),
            ),
          ],
        ),
      ],
    );
  }

  Widget _enfantLabeledField(String label, String value) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      mainAxisSize: MainAxisSize.min,
      children: [
        Text(
          label,
          style: TextStyle(
            fontSize: 12,
            fontWeight: FontWeight.w500,
            color: Colors.grey.shade700,
          ),
        ),
        const SizedBox(height: 4),
        ValidationReadOnlyField(value: value),
      ],
    );
  }

  Widget _buildEnfantPhotoSlot(String photoUrl, double width, double height) {
    const photoRadius = 8.0;
    return Container(
      width: width,
      height: height,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(photoRadius),
        border: Border.all(color: Colors.black.withOpacity(0.08)),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withOpacity(0.05),
            blurRadius: 6,
            offset: const Offset(0, 2),
          ),
        ],
      ),
      clipBehavior: Clip.antiAlias,
      child: photoUrl.isEmpty
          ? ColoredBox(
              color: Colors.grey.shade100,
              child: Center(
                child: Icon(Icons.person_outline, size: 32, color: Colors.grey.shade400),
              ),
            )
          : AuthNetworkImage(
              url: photoUrl,
              fit: BoxFit.cover,
              width: width,
              height: height,
              errorBuilder: (_, __, ___) => ColoredBox(
                color: Colors.grey.shade100,
                child: Center(
                  child: Icon(Icons.broken_image_outlined, size: 32, color: Colors.grey.shade400),
                ),
              ),
            ),
    );
  }

  static String _formatNom(String? lastName) {
    final n = (lastName ?? '').trim().toUpperCase();
    return n.isEmpty ? 'Non défini' : n;
  }

  /// Genre enfant : Garçon, Fille, ou "Non connu" (uniquement si l'enfant est à naître).
  static String _genreEnfantLabel(String? gender, String? status) {
    final g = (gender ?? '').trim().toUpperCase();
    final isANaitre = (status ?? '').trim().toLowerCase() == 'a_naitre';
    if (g == 'H') return 'Garçon';
    if (g == 'F') return 'Fille';
    if (isANaitre) return 'Non connu';
    if (g.isEmpty) return 'Non défini';
    return (gender ?? '').trim();
  }

  Widget _buildPresentationStep() {
    final p = widget.dossier.presentation ?? '';
    final text = p.trim().isEmpty ? 'Non défini' : p;
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        const Text(
          'Présentation',
          style: TextStyle(
              fontSize: 16, fontWeight: FontWeight.w600, color: Colors.black87),
        ),
        const SizedBox(height: 12),
        Expanded(
          child: LayoutBuilder(
            builder: (context, constraints) {
              return SingleChildScrollView(
                child: ConstrainedBox(
                  constraints: BoxConstraints(minHeight: constraints.maxHeight),
                  child: Container(
                    width: double.infinity,
                    padding: const EdgeInsets.symmetric(
                        horizontal: 12, vertical: 10),
                    decoration: BoxDecoration(
                      color: Colors.grey.shade50,
                      borderRadius: BorderRadius.circular(6),
                      border: Border.all(color: Colors.grey.shade300),
                    ),
                    child: SelectableText(
                      text,
                      style:
                          const TextStyle(color: Colors.black87, fontSize: 14),
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ],
    );
  }

  Widget _buildNavigation() {
    if (_step == 3) {
      return Row(
        children: [
          TextButton(onPressed: widget.onClose, child: const Text('Annuler')),
          const Spacer(),
          Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              TextButton(
                onPressed: () {
                  setState(() => _step = 2);
                  _emitStep();
                },
                child: const Text('Précédent'),
              ),
              const SizedBox(width: 8),
              if (_isEnAttente && _firstParentId != null) ...[
                OutlinedButton(
                    onPressed: _submitting ? null : _refuser,
                    child: const Text('Refuser')),
                const SizedBox(width: 12),
                ElevatedButton(
                  style: ValidationModalTheme.primaryElevatedStyle,
                  onPressed: _submitting ? null : _onValiderPressed,
                  child: Text(_submitting ? 'Envoi...' : 'Valider'),
                ),
              ] else if (!_isEnAttente)
                ElevatedButton(
                  style: ValidationModalTheme.primaryElevatedStyle,
                  onPressed: widget.onClose,
                  child: const Text('Fermer'),
                ),
            ],
          ),
        ],
      );
    }
    return Row(
      children: [
        TextButton(onPressed: widget.onClose, child: const Text('Annuler')),
        const Spacer(),
        if (_step > 0) ...[
          TextButton(
            onPressed: () {
              setState(() => _step--);
              _emitStep();
            },
            child: const Text('Précédent'),
          ),
          const SizedBox(width: 8),
        ],
        ElevatedButton(
          style: ValidationModalTheme.primaryElevatedStyle,
          onPressed: () {
            setState(() => _step++);
            _emitStep();
          },
          child: const Text('Suivant'),
        ),
      ],
    );
  }

  Future<void> _onValiderPressed() async {
    if (_submitting || _firstParentId == null) return;
    final ok = await showValidationValiderConfirmDialog(
      context,
      body:
          'Voulez-vous valider ce dossier famille ? Les comptes parents concernés seront confirmés.',
    );
    if (!mounted || !ok) return;
    await _valider();
  }

  Future<void> _valider() async {
    if (_submitting || _firstParentId == null) return;
    setState(() => _submitting = true);
    try {
      await UserService.validerDossierFamille(_firstParentId!);
      if (!mounted) return;
      widget.onSuccess();
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text(e is Exception
              ? e.toString().replaceFirst('Exception: ', '')
              : 'Erreur'),
          backgroundColor: Colors.red.shade700,
        ),
      );
    } finally {
      if (mounted) setState(() => _submitting = false);
    }
  }

  void _refuser() => setState(() => _showRefusForm = true);

  Widget _buildRefusPage() {
    return Padding(
      padding: const EdgeInsets.all(20),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Expanded(
            child: ValidationRefusForm(
              isSubmitting: _submitting,
              onCancel: widget.onClose,
              onPrevious: () => setState(() => _showRefusForm = false),
              onSubmit: (comment) {
                if (comment == null || comment.trim().isEmpty) return;
                _refuserEnvoyer(comment.trim());
              },
            ),
          ),
        ],
      ),
    );
  }

  /// Un seul appel : le back refuse tout le dossier famille (co-parents + mails). Ticket #110.
  Future<void> _refuserEnvoyer(String comment) async {
    if (_submitting) return;
    final parentId = _firstParentId?.trim();
    if (parentId == null || parentId.isEmpty || !_isEnAttente) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: const Text('Aucun compte en attente à refuser pour ce dossier.'),
          backgroundColor: Colors.red.shade700,
        ),
      );
      return;
    }
    setState(() => _submitting = true);
    try {
      await UserService.refuseUser(parentId, comment: comment);
      if (!mounted) return;
      final nbEnAttente = widget.dossier.parents
          .where((p) => p.statut == 'en_attente')
          .length;
      final msg = nbEnAttente > 1
          ? 'Refus enregistré. Un e-mail de reprise a été envoyé à chaque parent du dossier.'
          : 'Refus enregistré. Un e-mail avec le lien de reprise a été envoyé.';
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text(msg),
          duration: const Duration(seconds: 4),
        ),
      );
      widget.onSuccess();
    } catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text(e is Exception
              ? e.toString().replaceFirst('Exception: ', '')
              : 'Erreur'),
          backgroundColor: Colors.red.shade700,
        ),
      );
    } finally {
      if (mounted) setState(() => _submitting = false);
    }
  }
}
