import 'package:flutter/material.dart';
import 'package:p_tits_pas/widgets/admin/validation_modal_theme.dart';

/// Filtre optionnel (switch) sur la même ligne que la barre de recherche.
class AdminSelectToggleFilter<T> {
  final String label;
  final bool initialValue;

  /// Si le switch est activé, ne garde que les éléments pour lesquels
  /// [whenEnabled] renvoie `true`.
  final bool Function(T item) whenEnabled;

  const AdminSelectToggleFilter({
    required this.label,
    required this.whenEnabled,
    this.initialValue = true,
  });
}

/// Shell générique « rechercher + liste + sélection » pour les modales admin.
/// Utilisé par la sélection d'enfant (#146) et la sélection d'AM (#147).
class AdminSelectListModal<T> extends StatefulWidget {
  final String title;
  final String searchHint;
  final Future<List<T>> Function() loadItems;
  final bool Function(T item, String query) matchesQuery;
  final Widget Function(
    BuildContext context,
    T item,
    VoidCallback onSelect,
  ) itemBuilder;
  final String emptyMessage;
  final String noResultsMessage;
  final double modalWidth;

  /// Hauteur d'une carte (pour dimensionner la liste à ≥ [minVisibleCards]).
  final double cardExtent;

  /// Nombre minimum de cartes visibles dans la zone scrollable.
  final int minVisibleCards;

  /// Switch optionnel à droite du champ de recherche (ex. « Sans garde », « Libre »).
  final AdminSelectToggleFilter<T>? toggleFilter;

  /// Si fourni, appelé avant de valider la sélection.
  /// Retourne l'élément à pop (éventuellement rafraîchi), ou `null` pour annuler.
  final Future<T?> Function(
    BuildContext context,
    T item,
    Future<void> Function() reload,
  )? resolveSelect;

  const AdminSelectListModal({
    super.key,
    required this.title,
    required this.loadItems,
    required this.matchesQuery,
    required this.itemBuilder,
    this.searchHint = 'Rechercher…',
    this.emptyMessage = 'Aucun élément disponible',
    this.noResultsMessage = 'Aucun résultat pour cette recherche',
    this.modalWidth = 930,
    this.cardExtent = 52,
    this.minVisibleCards = 8,
    this.toggleFilter,
    this.resolveSelect,
  });

  static Future<T?> show<T>(
    BuildContext context, {
    required String title,
    required Future<List<T>> Function() loadItems,
    required bool Function(T item, String query) matchesQuery,
    required Widget Function(
      BuildContext context,
      T item,
      VoidCallback onSelect,
    ) itemBuilder,
    String searchHint = 'Rechercher…',
    String emptyMessage = 'Aucun élément disponible',
    String noResultsMessage = 'Aucun résultat pour cette recherche',
    double modalWidth = 930,
    double cardExtent = 52,
    int minVisibleCards = 8,
    AdminSelectToggleFilter<T>? toggleFilter,
    Future<T?> Function(
      BuildContext context,
      T item,
      Future<void> Function() reload,
    )? resolveSelect,
  }) {
    return showDialog<T>(
      context: context,
      builder: (ctx) => AdminSelectListModal<T>(
        title: title,
        loadItems: loadItems,
        matchesQuery: matchesQuery,
        itemBuilder: itemBuilder,
        searchHint: searchHint,
        emptyMessage: emptyMessage,
        noResultsMessage: noResultsMessage,
        modalWidth: modalWidth,
        cardExtent: cardExtent,
        minVisibleCards: minVisibleCards,
        toggleFilter: toggleFilter,
        resolveSelect: resolveSelect,
      ),
    );
  }

  @override
  State<AdminSelectListModal<T>> createState() =>
      _AdminSelectListModalState<T>();
}

class _AdminSelectListModalState<T> extends State<AdminSelectListModal<T>> {
  final _searchCtrl = TextEditingController();
  List<T> _all = [];
  bool _loading = true;
  String? _error;
  late bool _toggleOn;
  bool _resolving = false;

  double get _listHeight =>
      widget.cardExtent * widget.minVisibleCards;

  @override
  void initState() {
    super.initState();
    _toggleOn = widget.toggleFilter?.initialValue ?? false;
    _searchCtrl.addListener(() => setState(() {}));
    _load();
  }

  @override
  void dispose() {
    _searchCtrl.dispose();
    super.dispose();
  }

  Future<void> _load() async {
    setState(() {
      _loading = true;
      _error = null;
    });
    try {
      final list = await widget.loadItems();
      if (!mounted) return;
      setState(() {
        _all = list;
        _loading = false;
      });
    } catch (e) {
      if (!mounted) return;
      setState(() {
        _loading = false;
        _error = e.toString().replaceFirst('Exception: ', '');
      });
    }
  }

  Future<void> _handleSelect(T item) async {
    if (_resolving) return;
    final resolve = widget.resolveSelect;
    if (resolve == null) {
      Navigator.of(context).pop(item);
      return;
    }
    setState(() => _resolving = true);
    try {
      final chosen = await resolve(context, item, _load);
      if (!mounted || chosen == null) return;
      Navigator.of(context).pop(chosen);
    } finally {
      if (mounted) setState(() => _resolving = false);
    }
  }

  List<T> get _filtered {
    var list = _all;
    final toggle = widget.toggleFilter;
    if (toggle != null && _toggleOn) {
      list = list.where(toggle.whenEnabled).toList();
    }
    final q = _searchCtrl.text.trim().toLowerCase();
    if (q.isEmpty) return list;
    return list.where((item) => widget.matchesQuery(item, q)).toList();
  }

  @override
  Widget build(BuildContext context) {
    final toggle = widget.toggleFilter;

    return Dialog(
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
      child: ConstrainedBox(
        constraints: BoxConstraints(maxWidth: widget.modalWidth),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Padding(
              padding: const EdgeInsets.fromLTRB(18, 16, 4, 0),
              child: Row(
                children: [
                  Expanded(
                    child: Text(
                      widget.title,
                      style: const TextStyle(
                        fontSize: 18,
                        fontWeight: FontWeight.w700,
                      ),
                    ),
                  ),
                  IconButton(
                    icon: const Icon(Icons.close),
                    tooltip: 'Fermer',
                    onPressed: () => Navigator.of(context).pop(),
                  ),
                ],
              ),
            ),
            const Divider(height: 1),
            Padding(
              padding: const EdgeInsets.fromLTRB(16, 12, 16, 12),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  Row(
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      Expanded(
                        child: TextField(
                          controller: _searchCtrl,
                          decoration: InputDecoration(
                            isDense: true,
                            hintText: widget.searchHint,
                            prefixIcon: const Icon(Icons.search, size: 20),
                            border: OutlineInputBorder(
                              borderRadius: BorderRadius.circular(8),
                            ),
                            contentPadding: const EdgeInsets.symmetric(
                              horizontal: 12,
                              vertical: 12,
                            ),
                          ),
                        ),
                      ),
                      if (toggle != null) ...[
                        const SizedBox(width: 12),
                        Text(
                          toggle.label,
                          style: const TextStyle(fontSize: 13),
                        ),
                        const SizedBox(width: 4),
                        Switch(
                          value: _toggleOn,
                          activeColor:
                              ValidationModalTheme.primaryActionBackground,
                          onChanged: (v) => setState(() => _toggleOn = v),
                        ),
                      ],
                    ],
                  ),
                  const SizedBox(height: 12),
                  SizedBox(
                    height: _listHeight,
                    child: DecoratedBox(
                      decoration: BoxDecoration(
                        color: Colors.white,
                        borderRadius: BorderRadius.circular(8),
                        border: Border.all(color: Colors.grey.shade300),
                      ),
                      child: ClipRRect(
                        borderRadius: BorderRadius.circular(8),
                        child: _buildBody(),
                      ),
                    ),
                  ),
                  const SizedBox(height: 12),
                  Row(
                    children: [
                      const Spacer(),
                      TextButton(
                        onPressed: () => Navigator.of(context).pop(),
                        child: const Text('Annuler'),
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildBody() {
    if (_loading) {
      return const Center(
        child: CircularProgressIndicator(
          color: ValidationModalTheme.primaryActionBackground,
        ),
      );
    }

    if (_error != null) {
      return Center(
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Icon(Icons.error_outline, size: 40, color: Colors.red.shade400),
              const SizedBox(height: 12),
              Text(
                _error!,
                textAlign: TextAlign.center,
                style: TextStyle(color: Colors.red.shade700),
              ),
              const SizedBox(height: 12),
              TextButton.icon(
                onPressed: _load,
                icon: const Icon(Icons.refresh),
                label: const Text('Réessayer'),
              ),
            ],
          ),
        ),
      );
    }

    final items = _filtered;
    if (_all.isEmpty) {
      return Center(
        child: Text(
          widget.emptyMessage,
          style: const TextStyle(fontSize: 14, color: Colors.black54),
        ),
      );
    }

    if (items.isEmpty) {
      return Center(
        child: Text(
          widget.noResultsMessage,
          style: const TextStyle(fontSize: 14, color: Colors.black54),
        ),
      );
    }

    return ListView.builder(
      padding: const EdgeInsets.fromLTRB(8, 8, 8, 4),
      itemExtent: widget.cardExtent,
      itemCount: items.length,
      itemBuilder: (context, i) {
        final item = items[i];
        return widget.itemBuilder(
          context,
          item,
          () => _handleSelect(item),
        );
      },
    );
  }
}
