import 'package:flutter/material.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/nir_utils.dart';
import 'package:p_tits_pas/models/user.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/admin_detail_modal.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 AM : étapes sobres (label/valeur), récap, Valider/Refuser/Annuler, page refus. Ticket #107.
class ValidationAmWizard extends StatefulWidget {
  final DossierAM dossier;
  final VoidCallback onClose;
  final VoidCallback onSuccess;
  final void Function(int step, int total)? onStepChanged;

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

  @override
  State<ValidationAmWizard> createState() => _ValidationAmWizardState();
}

class _ValidationAmWizardState extends State<ValidationAmWizard> {
  int _step = 0;
  bool _showRefusForm = false;
  bool _submitting = false;

  static const int _stepCount = 3;

  bool get _isEnAttente => widget.dossier.user.statut == 'en_attente';

  static String _v(String? s) =>
      (s != null && s.trim().isNotEmpty) ? s.trim() : '–';

  /// Présentation lisible : `1 12 34 56 789 012 - 34` (15 caractères utiles requis).
  static String _formatNirForDisplay(String? nir) {
    final v = _v(nir);
    if (v == '–') return v;
    final raw = nirToRaw(v).toUpperCase();
    return raw.length == 15 ? formatNir(raw) : v;
  }

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

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

  /// Panneau photo + grille droite : NIR|naissance, ville|pays, agrément|date, capa|places.
  List<AdminDetailField> _photoProFields(DossierAM d) {
    final u = d.user;
    return [
      AdminDetailField(label: 'NIR', value: _formatNirForDisplay(d.nir)),
      AdminDetailField(
        label: 'Date de naissance',
        value: formatIsoDateFr(u.dateNaissance),
      ),
      AdminDetailField(
        label: 'Ville de naissance',
        value: _v(u.lieuNaissanceVille),
      ),
      AdminDetailField(
        label: 'Pays de naissance',
        value: _v(u.lieuNaissancePays),
      ),
      AdminDetailField(label: 'N° Agrément', value: _v(d.numeroAgrement)),
      AdminDetailField(
        label: 'Date d’agrément',
        value: formatIsoDateFr(d.dateAgrement),
      ),
      AdminDetailField(
        label: 'Capacité max (enfants)',
        value: d.nbMaxEnfants != null ? d.nbMaxEnfants.toString() : '–',
      ),
      AdminDetailField(
        label: 'Places disponibles',
        value: d.placesDisponibles != null
            ? d.placesDisponibles.toString()
            : '–',
      ),
    ];
  }

  static const List<int> _photoProRowLayout = [2, 2, 2, 2];

  /// Proportion photo d’identité (35×45 mm).
  static const double _idPhotoAspectRatio = 35 / 45;

  static const double _photoProGap = 24;
  /// Largeur mini réservée aux champs (évite une colonne photo trop gourmande).
  static const double _proColumnMinWidth = 260;
  static const double _photoColumnMinWidth = 160;

  /// URL complète pour la photo : si relatif, préfixe [ApiConfig.baseUrl] (ex. `/api/v1/uploads/...`).
  static String _fullPhotoUrl(String? url) => ApiConfig.absoluteMediaUrl(url);

  Widget _buildPhotoSection(AppUser u) {
    final photoUrl = _fullPhotoUrl(u.photoUrl);
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        Expanded(
          child: Padding(
            padding: const EdgeInsets.only(right: 8),
            child: LayoutBuilder(
              builder: (context, c) {
                // Cadre clair : une seule épaisseur partout (photo + padding identique haut/bas/gauche/droite).
                const uniformFrame = 8.0;
                final maxPhotoW =
                    (c.maxWidth - 2 * uniformFrame).clamp(0.0, double.infinity);
                final maxPhotoH =
                    (c.maxHeight - 2 * uniformFrame).clamp(0.0, double.infinity);
                const ar = _idPhotoAspectRatio;
                double ph = maxPhotoH;
                double pw = ph * ar;
                if (pw > maxPhotoW) {
                  pw = maxPhotoW;
                  ph = pw / ar;
                }
                return Align(
                  alignment: Alignment.center,
                  child: Container(
                    decoration: BoxDecoration(
                      color: Colors.grey.shade100,
                      borderRadius: BorderRadius.circular(8),
                      border: Border.all(color: Colors.grey.shade300),
                    ),
                    clipBehavior: Clip.antiAlias,
                    child: Padding(
                      padding: const EdgeInsets.all(uniformFrame),
                      child: ClipRRect(
                        borderRadius: BorderRadius.circular(6),
                        child: SizedBox(
                          width: pw,
                          height: ph,
                          child: photoUrl.isEmpty
                              ? ColoredBox(
                                  color: Colors.grey.shade200,
                                  child: Column(
                                    mainAxisAlignment: MainAxisAlignment.center,
                                    children: [
                                      Icon(Icons.person_off_outlined,
                                          size: 40,
                                          color: Colors.grey.shade400),
                                      const SizedBox(height: 8),
                                      Text(
                                        'Aucune photo fournie',
                                        style: TextStyle(
                                            color: Colors.grey.shade600,
                                            fontSize: 12),
                                      ),
                                    ],
                                  ),
                                )
                              : AuthNetworkImage(
                                  url: photoUrl,
                                  fit: BoxFit.cover,
                                  width: pw,
                                  height: ph,
                                  loadingBuilder: (_, child, progress) {
                                    if (progress == null) return child;
                                    return ColoredBox(
                                      color: Colors.grey.shade200,
                                      child: Center(
                                        child: CircularProgressIndicator(
                                          value: progress.expectedTotalBytes !=
                                                  null
                                              ? progress.cumulativeBytesLoaded /
                                                  (progress.expectedTotalBytes!)
                                              : null,
                                        ),
                                      ),
                                    );
                                  },
                                  errorBuilder: (_, __, ___) => ColoredBox(
                                    color: Colors.grey.shade200,
                                    child: Column(
                                      mainAxisAlignment:
                                          MainAxisAlignment.center,
                                      children: [
                                        Icon(Icons.broken_image_outlined,
                                            size: 40,
                                            color: Colors.grey.shade400),
                                        const SizedBox(height: 8),
                                        Text(
                                          'Impossible de charger la photo',
                                          style: TextStyle(
                                              color: Colors.grey.shade600,
                                              fontSize: 12),
                                        ),
                                      ],
                                    ),
                                  ),
                                ),
                        ),
                      ),
                    ),
                  ),
                );
              },
            ),
          ),
        ),
      ],
    );
  }

  @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;
    final u = d.user;
    switch (_step) {
      case 0:
        return LayoutBuilder(
          builder: (context, constraints) {
            return SingleChildScrollView(
              child: ConstrainedBox(
                constraints: BoxConstraints(minWidth: constraints.maxWidth),
                child: IdentityBlock.readOnlyFromUser(
                  u,
                  title: 'Identité et coordonnées',
                  emptyLabel: '–',
                ),
              ),
            );
          },
        );
      case 1:
        // Pas de SingleChildScrollView sur la Row (hauteur non bornée). Défilement à droite.
        // Largeur photo ≈ ratio × hauteur utile, plafonnée pour laisser au moins [_proColumnMinWidth] aux champs.
        return LayoutBuilder(
          builder: (context, c) {
            final maxRowW = c.maxWidth;
            final maxRowH = c.maxHeight;
            const photoHeaderH = 0.0;
            final bodyH = (maxRowH - photoHeaderH).clamp(0.0, double.infinity);
            final idealPhotoW =
                bodyH * _idPhotoAspectRatio + 16; // marge approx. cadre clair
            final maxPhotoW = (maxRowW - _photoProGap - _proColumnMinWidth)
                .clamp(0.0, double.infinity);
            var photoW = idealPhotoW.clamp(_photoColumnMinWidth, 360.0);
            if (photoW > maxPhotoW) photoW = maxPhotoW;
            photoW = photoW.clamp(0.0, maxRowW - _photoProGap);

            return Row(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                SizedBox(
                  width: photoW,
                  child: _buildPhotoSection(u),
                ),
                const SizedBox(width: _photoProGap),
                Expanded(
                  child: LayoutBuilder(
                    builder: (context, constraints) {
                      return SingleChildScrollView(
                        child: ConstrainedBox(
                          constraints: BoxConstraints(
                              minWidth: constraints.maxWidth),
                          child: ValidationDetailSection(
                            title: 'Dossier professionnel',
                            fields: _photoProFields(d),
                            rowLayout: _photoProRowLayout,
                          ),
                        ),
                      );
                    },
                  ),
                ),
              ],
            );
          },
        );
      case 2:
        final presentation =
            (d.presentation != null && d.presentation!.trim().isNotEmpty)
                ? d.presentation!
                : '–';
        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(
                          presentation,
                          style: const TextStyle(
                              color: Colors.black87, fontSize: 14),
                        ),
                      ),
                    ),
                  );
                },
              ),
            ),
          ],
        );
      default:
        return const SizedBox();
    }
  }

  Widget _buildNavigation() {
    if (_step == 2) {
      return Row(
        children: [
          TextButton(onPressed: widget.onClose, child: const Text('Annuler')),
          const Spacer(),
          Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              TextButton(
                onPressed: () {
                  setState(() => _step = 1);
                  _emitStep();
                },
                child: const Text('Précédent'),
              ),
              const SizedBox(width: 8),
              if (_isEnAttente) ...[
                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
                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) return;
    final ok = await showValidationValiderConfirmDialog(
      context,
      body:
          'Voulez-vous valider le dossier de cette assistante maternelle ? Cette action confirme le compte.',
    );
    if (!mounted || !ok) return;
    await _valider();
  }

  Future<void> _valider() async {
    if (_submitting) return;
    setState(() => _submitting = true);
    try {
      await UserService.validateUser(widget.dossier.user.id);
      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());
              },
            ),
          ),
        ],
      ),
    );
  }

  Future<void> _refuserEnvoyer(String comment) async {
    if (_submitting) return;
    setState(() => _submitting = true);
    try {
      await UserService.refuseUser(widget.dossier.user.id, comment: comment);
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: const Text(
            'Refus enregistré. Un e-mail avec le lien de reprise a été envoyé.',
          ),
          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);
    }
  }
}
