import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../bloc/organizations_bloc.dart';
import '../../bloc/organizations_event.dart';
import '../../bloc/organizations_state.dart';
import '../../data/models/organization_model.dart';
import '../widgets/organization_card.dart';
import '../widgets/create_organization_dialog.dart';
import '../widgets/edit_organization_dialog.dart';
import 'organization_detail_page.dart';
import 'org_types_page.dart';
import '../../../../shared/design_system/unionflow_design_system.dart';
import '../../../../shared/design_system/components/animated_fade_in.dart';
import '../../../../shared/design_system/components/animated_slide_in.dart';
import '../../../../shared/design_system/components/african_pattern_background.dart';
import '../../../../shared/design_system/components/uf_app_bar.dart';
import '../../../../features/authentication/presentation/bloc/auth_bloc.dart';
import '../../../../features/authentication/data/models/user_role.dart';
import '../../bloc/org_switcher_bloc.dart';


/// Page de gestion des organisations - Interface sophistiquée et exhaustive
class OrganizationsPage extends StatefulWidget {
  const OrganizationsPage({super.key});

  @override
  State<OrganizationsPage> createState() => _OrganizationsPageState();
}

class _OrganizationsPageState extends State<OrganizationsPage> with TickerProviderStateMixin {
  final TextEditingController _searchController = TextEditingController();
  TabController? _tabController;
  final ScrollController _scrollController = ScrollController();
  List<String?> _availableTypes = [];

  // ── Nouvelles fonctionnalités (parité Annuaire Membres) ──
  bool _isGridView = false;
  String _filterStatut = 'Tous';
  static const _statutFilters = ['Tous', 'Active', 'En création', 'Inactive', 'Suspendue', 'Dissoute'];
  static const _statutFilterMapping = {
    'Active': 'ACTIVE',
    'En création': 'EN_CREATION',
    'Inactive': 'INACTIVE',
    'Suspendue': 'SUSPENDUE',
    'Dissoute': 'DISSOUTE',
  };

  /// Cache de la dernière liste connue.
  /// Évite de perdre l'affichage quand le bloc passe dans un état non-liste
  /// (OrganizationLoaded, OrganizationCreated, etc.) après navigation vers
  /// la page de détail ou une action CRUD.
  OrganizationsLoaded? _cachedListState;

  @override
  void initState() {
    super.initState();
    _scrollController.addListener(_onScroll);
  }

  @override
  void dispose() {
    _tabController?.dispose();
    _searchController.dispose();
    _scrollController.dispose();
    super.dispose();
  }

  void _onScroll() {
    if (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent * 0.9) {
      context.read<OrganizationsBloc>().add(const LoadMoreOrganizations());
    }
  }

  /// Titre dynamique de l'AppBar selon le rôle et le nombre d'organisations.
  ///
  /// SuperAdmin → "Gestion des Organisations"
  /// OrgAdmin 1 org → "Mon Organisation"
  /// OrgAdmin 2+ orgs → "Mes Organisations"
  String _appBarTitle(BuildContext context) {
    final authState = context.read<AuthBloc>().state;
    if (authState is! AuthAuthenticated) return 'Organisations';
    if (authState.effectiveRole == UserRole.superAdmin) {
      return 'Gestion des Organisations';
    }
    try {
      final switcherState = context.read<OrgSwitcherBloc>().state;
      if (switcherState is OrgSwitcherLoaded) {
        return switcherState.organisations.length > 1
            ? 'Mes Organisations'
            : 'Mon Organisation';
      }
    } catch (_) {}
    return 'Mon Organisation';
  }

  List<String?> _calculateAvailableTypes(List<OrganizationModel> organizations) {
    if (organizations.isEmpty) return [null];
    final types = organizations.map((org) => org.typeOrganisation).toSet().toList()..sort((a, b) => a.compareTo(b));
    return [null, ...types];
  }

  void _updateTabController(List<String?> newTypes) {
    if (_availableTypes.length != newTypes.length || !_availableTypes.every((t) => newTypes.contains(t))) {
      _availableTypes = newTypes;
      _tabController?.dispose();
      _tabController = TabController(length: _availableTypes.length, vsync: this);
    }
  }

  @override
  Widget build(BuildContext context) {
    return BlocConsumer<OrganizationsBloc, OrganizationsState>(
      listener: (context, state) {
        if (state is OrganizationsError) {
          ScaffoldMessenger.of(context).showSnackBar(SnackBar(
            content: Text(state.message),
            backgroundColor: Theme.of(context).colorScheme.error,
            duration: const Duration(seconds: 4),
            action: SnackBarAction(
              label: 'Réessayer',
              textColor: AppColors.onError,
              onPressed: () => context.read<OrganizationsBloc>().add(const LoadOrganizations(refresh: true)),
            ),
          ));
        } else if (state is OrganizationCreated) {
          ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
            content: Text('Organisation créée avec succès'),
            backgroundColor: AppColors.success,
            duration: Duration(seconds: 2),
          ));
        } else if (state is OrganizationUpdated) {
          ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
            content: Text('Organisation mise à jour avec succès'),
            backgroundColor: AppColors.success,
            duration: Duration(seconds: 2),
          ));
        } else if (state is OrganizationDeleted) {
          ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
            content: Text('Organisation supprimée avec succès'),
            backgroundColor: AppColors.success,
            duration: Duration(seconds: 2),
          ));
        }
      },
      builder: (context, state) {
        // Détermine la liste d'organisations courante (avec fallback cache
        // pour ne pas perdre les onglets entre navigations)
        OrganizationsLoaded? loadedState;
        if (state is OrganizationsLoaded) {
          loadedState = state;
        } else if (_cachedListState != null) {
          loadedState = _cachedListState;
        }
        final availableTypes = loadedState != null
            ? _calculateAvailableTypes(loadedState.organizations)
            : <String?>[];
        _updateTabController(availableTypes);

        return AfricanPatternBackground(
          child: Scaffold(
            backgroundColor: Colors.transparent,
            appBar: UFAppBar(
              title: _appBarTitle(context),
              moduleGradient: ModuleColors.organisationsGradient,
              elevation: 0,
              actions: [
                IconButton(
                  icon: Icon(_isGridView ? Icons.view_list_rounded : Icons.grid_view_rounded),
                  onPressed: () => setState(() => _isGridView = !_isGridView),
                  tooltip: _isGridView ? 'Vue liste' : 'Vue grille',
                ),
                IconButton(
                  icon: const Icon(Icons.category_outlined),
                  onPressed: () => Navigator.of(context).push(MaterialPageRoute<void>(builder: (_) => const OrgTypesPage())),
                  tooltip: 'Types d\'organisations',
                ),
                IconButton(
                  icon: const Icon(Icons.refresh),
                  onPressed: () => context.read<OrganizationsBloc>().add(const RefreshOrganizations()),
                  tooltip: 'Rafraîchir',
                ),
              ],
              bottom: (_tabController != null && availableTypes.isNotEmpty)
                  ? TabBar(
                      controller: _tabController!,
                      isScrollable: true,
                      labelColor: Colors.white,
                      unselectedLabelColor: Colors.white70,
                      indicatorColor: Colors.white,
                      indicatorSize: TabBarIndicatorSize.label,
                      labelStyle: AppTypography.actionText
                          .copyWith(fontSize: 10, fontWeight: FontWeight.bold),
                      onTap: (i) {
                        final selectedType = availableTypes[i];
                        if (selectedType != null) {
                          context
                              .read<OrganizationsBloc>()
                              .add(FilterOrganizationsByType(selectedType));
                        } else {
                          context
                              .read<OrganizationsBloc>()
                              .add(const ClearOrganizationsFilters());
                        }
                      },
                      tabs: availableTypes
                          .map((type) => Tab(
                              child: Text((type ?? 'Toutes').toUpperCase())))
                          .toList(),
                    )
                  : null,
            ),
            body: SafeArea(child: _buildBody(context, state)),
            floatingActionButton: _buildActionButton(context, state),
          ),
        );
      },
    );
  }

  Widget _buildBody(BuildContext context, OrganizationsState state) {
    // Mémoriser le dernier état liste dès qu'on l'obtient
    if (state is OrganizationsLoaded) _cachedListState = state;

    if (state is OrganizationsInitial || state is OrganizationsLoading) {
      // Données déjà en cache (ex. retour depuis détail) → afficher sans loader
      if (_cachedListState != null) return _buildLoadedBody(context, _cachedListState!);
      return _buildLoadingState(context);
    }
    if (state is OrganizationsLoaded) {
      return _buildLoadedBody(context, state);
    }
    if (state is OrganizationsLoadingMore) {
      return SingleChildScrollView(
        controller: _scrollController,
        padding: const EdgeInsets.all(SpacingTokens.md),
        physics: const AlwaysScrollableScrollPhysics(),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            _buildLoadingMorePlaceholder(context, state.currentOrganizations),
            Padding(
              padding: const EdgeInsets.all(SpacingTokens.md),
              child: Center(child: CircularProgressIndicator(color: ModuleColors.organisations)),
            ),
            const SizedBox(height: 80),
          ],
        ),
      );
    }
    if (state is OrganizationsError) return _buildErrorState(context, state);

    // État non-liste (OrganizationLoaded, OrganizationCreated, etc.) :
    // réutiliser la liste en cache plutôt que d'afficher un loader indéfini.
    if (_cachedListState != null) return _buildLoadedBody(context, _cachedListState!);
    return _buildLoadingState(context);
  }

  /// Contenu principal de la liste — extrait pour être réutilisable via le cache.
  /// Note : les onglets de catégories (TabBar) sont désormais dans
  /// UFAppBar.bottom (pattern Adhésions). _updateTabController est appelé
  /// au niveau supérieur dans le builder du BlocConsumer.
  Widget _buildLoadedBody(BuildContext context, OrganizationsLoaded state) {
    return RefreshIndicator(
      color: ModuleColors.organisations,
      onRefresh: () async => context.read<OrganizationsBloc>().add(const RefreshOrganizations()),
      child: SingleChildScrollView(
        controller: _scrollController,
        padding: const EdgeInsets.all(SpacingTokens.md),
        physics: const AlwaysScrollableScrollPhysics(),
        child: AnimatedFadeIn(
          duration: const Duration(milliseconds: 400),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              AnimatedSlideIn(
                duration: const Duration(milliseconds: 500),
                curve: Curves.easeOut,
                child: _buildKpiHeader(context, state),
              ),
              const SizedBox(height: SpacingTokens.md),
              AnimatedSlideIn(
                duration: const Duration(milliseconds: 600),
                curve: Curves.easeOut,
                child: _buildSearchBar(context, state),
              ),
              const SizedBox(height: SpacingTokens.sm),
              _buildStatutChips(context),
              const SizedBox(height: SpacingTokens.md),
              AnimatedSlideIn(
                duration: const Duration(milliseconds: 800),
                curve: Curves.easeOut,
                child: _isGridView
                    ? _buildOrganizationsGrid(context, state)
                    : _buildOrganizationsList(context, state),
              ),
              const SizedBox(height: 80),
            ],
          ),
        ),
      ),
    );
  }

  // ─── KPI Header ───────────────────────────────────────────────────────────

  Widget _buildKpiHeader(BuildContext context, OrganizationsLoaded state) {
    final orgs = state.organizations;
    final total = orgs.length;
    final active = orgs.where((o) => o.statut == StatutOrganization.active).length;
    final suspended = orgs.where((o) => o.statut == StatutOrganization.suspendue).length;
    final totalMembers = orgs.fold<int>(0, (sum, o) => sum + o.nombreMembres);
    final activePercent = total > 0 ? active / total : 0.0;

    return Container(
      padding: const EdgeInsets.fromLTRB(12, 8, 12, 10),
      decoration: BoxDecoration(
        color: Theme.of(context).colorScheme.surface,
        borderRadius: BorderRadius.circular(RadiusTokens.lg),
        border: Border.all(color: Theme.of(context).colorScheme.outlineVariant, width: 1),
        boxShadow: const [BoxShadow(color: AppColors.shadow, blurRadius: 8, offset: Offset(0, 2))],
      ),
      child: Row(
        children: [
          _kpiTile(context, 'Total', total.toString(), ModuleColors.organisations, Icons.business_outlined),
          _kpiSep(context),
          _kpiTileProgress(context, 'Actives', '${(activePercent * 100).toStringAsFixed(0)}%', AppColors.success, activePercent),
          _kpiSep(context),
          _kpiTile(context, 'Membres', totalMembers.toString(), ModuleColors.organisations, Icons.people_outline),
          _kpiSep(context),
          _kpiTile(context, 'Suspendues', suspended.toString(), AppColors.warning, Icons.pause_circle_outline),
        ],
      ),
    );
  }

  Widget _kpiTile(BuildContext context, String label, String value, Color color, IconData icon) {
    return Expanded(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(icon, size: 14, color: color),
          const SizedBox(height: 1),
          Text(value, style: TextStyle(fontSize: 17, fontWeight: FontWeight.w800, color: color)),
          Text(label, style: TextStyle(fontSize: 9, fontWeight: FontWeight.w600, color: color.withOpacity(0.75)), textAlign: TextAlign.center),
        ],
      ),
    );
  }

  Widget _kpiTileProgress(BuildContext context, String label, String value, Color color, double progress) {
    return Expanded(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Text(value, style: TextStyle(fontSize: 17, fontWeight: FontWeight.w800, color: color)),
          const SizedBox(height: 3),
          ClipRRect(
            borderRadius: BorderRadius.circular(2),
            child: LinearProgressIndicator(
              value: progress,
              backgroundColor: color.withOpacity(0.15),
              valueColor: AlwaysStoppedAnimation<Color>(color),
              minHeight: 4,
            ),
          ),
          const SizedBox(height: 2),
          Text(label, style: TextStyle(fontSize: 9, fontWeight: FontWeight.w600, color: color.withOpacity(0.75)), textAlign: TextAlign.center),
        ],
      ),
    );
  }

  Widget _kpiSep(BuildContext context) =>
      Container(width: 1, height: 42, color: Theme.of(context).colorScheme.outlineVariant);

  // ─── Barre de recherche ───────────────────────────────────────────────────

  Widget _buildSearchBar(BuildContext context, OrganizationsLoaded state) {
    return Container(
      decoration: BoxDecoration(
        color: Theme.of(context).colorScheme.surface,
        borderRadius: BorderRadius.circular(RadiusTokens.lg),
        border: Border.all(color: Theme.of(context).colorScheme.outlineVariant, width: 1),
        boxShadow: const [BoxShadow(color: AppColors.shadow, blurRadius: 8, offset: Offset(0, 2))],
      ),
      child: TextField(
        controller: _searchController,
        onChanged: (v) => context.read<OrganizationsBloc>().add(SearchOrganizations(v)),
        style: TextStyle(fontSize: 14, color: Theme.of(context).colorScheme.onSurface),
        decoration: InputDecoration(
          hintText: 'Rechercher par nom, type, localisation...',
          hintStyle: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant, fontSize: 14),
          prefixIcon: const Icon(Icons.search, color: ModuleColors.organisations),
          suffixIcon: _searchController.text.isNotEmpty
              ? IconButton(
                  onPressed: () {
                    _searchController.clear();
                    context.read<OrganizationsBloc>().add(const SearchOrganizations(''));
                  },
                  icon: Icon(Icons.clear, color: Theme.of(context).colorScheme.onSurfaceVariant),
                )
              : null,
          border: OutlineInputBorder(borderRadius: BorderRadius.circular(RadiusTokens.lg), borderSide: BorderSide.none),
          enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(RadiusTokens.lg), borderSide: BorderSide.none),
          focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(RadiusTokens.lg), borderSide: const BorderSide(color: ModuleColors.organisations, width: 1.5)),
          filled: true,
          fillColor: Theme.of(context).colorScheme.surface,
          contentPadding: const EdgeInsets.symmetric(horizontal: SpacingTokens.md, vertical: SpacingTokens.sm),
        ),
      ),
    );
  }

  // ─── Chips de filtre par statut ─────────────────────────────────────────

  Widget _buildStatutChips(BuildContext context) {
    return SingleChildScrollView(
      scrollDirection: Axis.horizontal,
      child: Row(
        children: _statutFilters.map((label) {
          final isSelected = _filterStatut == label;
          return Padding(
            padding: const EdgeInsets.only(right: 8),
            child: GestureDetector(
              onTap: () => setState(() => _filterStatut = label),
              child: AnimatedContainer(
                duration: const Duration(milliseconds: 150),
                padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
                decoration: BoxDecoration(
                  color: isSelected ? ModuleColors.organisations : Colors.transparent,
                  borderRadius: BorderRadius.circular(20),
                  border: Border.all(
                    color: isSelected ? ModuleColors.organisations : Theme.of(context).colorScheme.outline,
                    width: 1,
                  ),
                ),
                child: Text(
                  label,
                  style: TextStyle(
                    fontSize: 12,
                    fontWeight: FontWeight.w600,
                    color: isSelected ? AppColors.onPrimary : Theme.of(context).colorScheme.onSurfaceVariant,
                  ),
                ),
              ),
            ),
          );
        }).toList(),
      ),
    );
  }

  /// Filtre les organisations par statut (chips) en plus des filtres BLoC (type + recherche)
  List<OrganizationModel> _applyStatutFilter(List<OrganizationModel> orgs) {
    if (_filterStatut == 'Tous') return orgs;
    final mappedStatut = _statutFilterMapping[_filterStatut];
    if (mappedStatut == null) return orgs;
    return orgs.where((o) => o.statut.name.toUpperCase() == mappedStatut).toList();
  }

  // ─── Liste des organisations (avec swipe) ─────────────────────────────────

  Widget _buildOrganizationsList(BuildContext context, OrganizationsLoaded state) {
    final organizations = _applyStatutFilter(state.filteredOrganizations);
    if (organizations.isEmpty) return _buildEmptyState(context);

    final authState = context.read<AuthBloc>().state;
    final canManageOrgs = authState is AuthAuthenticated &&
        (authState.effectiveRole == UserRole.superAdmin || authState.effectiveRole == UserRole.orgAdmin);

    return ListView.separated(
      shrinkWrap: true,
      physics: const NeverScrollableScrollPhysics(),
      itemCount: organizations.length,
      separatorBuilder: (_, __) => const SizedBox(height: SpacingTokens.sm),
      itemBuilder: (context, i) {
        final org = organizations[i];
        return AnimatedFadeIn(
          duration: Duration(milliseconds: 300 + (i * 50)),
          child: _buildSwipeableCard(context, org, canManageOrgs),
        );
      },
    );
  }

  // ─── Vue grille ───────────────────────────────────────────────────────────

  Widget _buildOrganizationsGrid(BuildContext context, OrganizationsLoaded state) {
    final organizations = _applyStatutFilter(state.filteredOrganizations);
    if (organizations.isEmpty) return _buildEmptyState(context);

    return GridView.builder(
      shrinkWrap: true,
      physics: const NeverScrollableScrollPhysics(),
      gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
        mainAxisSpacing: 8,
        crossAxisSpacing: 8,
        childAspectRatio: 0.85,
      ),
      itemCount: organizations.length,
      itemBuilder: (context, i) {
        final org = organizations[i];
        return _buildGridCard(context, org);
      },
    );
  }

  Widget _buildGridCard(BuildContext context, OrganizationModel org) {
    final scheme = Theme.of(context).colorScheme;
    final statutColor = Color(int.parse(org.statut.color.substring(1), radix: 16) + 0xFF000000);

    return GestureDetector(
      onTap: () => _showOrganizationDetails(org),
      child: Container(
        decoration: BoxDecoration(
          color: scheme.surface,
          borderRadius: BorderRadius.circular(12),
          border: Border.all(color: scheme.outline.withOpacity(0.3)),
          boxShadow: [BoxShadow(color: AppColors.shadow, blurRadius: 4, offset: const Offset(0, 2))],
        ),
        padding: const EdgeInsets.all(12),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // Icône + statut
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Container(
                  padding: const EdgeInsets.all(8),
                  decoration: BoxDecoration(
                    color: ModuleColors.organisations.withOpacity(0.1),
                    borderRadius: BorderRadius.circular(8),
                  ),
                  child: const Icon(Icons.business_outlined, size: 20, color: ModuleColors.organisations),
                ),
                Container(
                  padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
                  decoration: BoxDecoration(
                    color: statutColor.withOpacity(0.1),
                    borderRadius: BorderRadius.circular(10),
                  ),
                  child: Text(
                    org.statut.displayName,
                    style: TextStyle(fontSize: 9, fontWeight: FontWeight.w700, color: statutColor),
                  ),
                ),
              ],
            ),
            const SizedBox(height: 10),
            // Nom
            Text(
              org.nom,
              style: TextStyle(fontSize: 14, fontWeight: FontWeight.w700, color: scheme.onSurface),
              maxLines: 2,
              overflow: TextOverflow.ellipsis,
            ),
            if (org.nomCourt?.isNotEmpty == true)
              Text(org.nomCourt!, style: TextStyle(fontSize: 10, color: scheme.onSurfaceVariant)),
            const Spacer(),
            // Type
            Text(
              org.typeOrganisation,
              style: TextStyle(fontSize: 10, color: ModuleColors.organisations, fontWeight: FontWeight.w600),
            ),
            const SizedBox(height: 4),
            // Localisation + membres
            Row(
              children: [
                if (org.ville?.isNotEmpty == true) ...[
                  Icon(Icons.location_on_outlined, size: 11, color: scheme.onSurfaceVariant),
                  const SizedBox(width: 2),
                  Expanded(
                    child: Text(
                      org.ville!,
                      style: TextStyle(fontSize: 10, color: scheme.onSurfaceVariant),
                      maxLines: 1,
                      overflow: TextOverflow.ellipsis,
                    ),
                  ),
                ],
                Icon(Icons.people_outline, size: 11, color: scheme.onSurfaceVariant),
                const SizedBox(width: 2),
                Text(
                  '${org.nombreMembres}',
                  style: TextStyle(fontSize: 10, fontWeight: FontWeight.w600, color: scheme.onSurface),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  // ─── Swipe actions ────────────────────────────────────────────────────────

  Widget _buildSwipeableCard(BuildContext context, OrganizationModel org, bool canManage) {
    if (!canManage) {
      return OrganizationCard(
        organization: org,
        onTap: () => _showOrganizationDetails(org),
        showActions: false,
      );
    }

    return Dismissible(
      key: Key('org_swipe_${org.id}'),
      direction: DismissDirection.horizontal,
      confirmDismiss: (dir) async {
        if (dir == DismissDirection.startToEnd) {
          _showEditOrganizationDialog(org);
        } else if (dir == DismissDirection.endToStart) {
          _confirmDeleteOrganization(org);
        }
        return false;
      },
      background: Container(
        margin: const EdgeInsets.symmetric(vertical: 1),
        decoration: BoxDecoration(
          color: ModuleColors.organisations.withOpacity(0.13),
          borderRadius: BorderRadius.circular(8),
        ),
        alignment: Alignment.centerLeft,
        padding: const EdgeInsets.symmetric(horizontal: 20),
        child: const Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(Icons.edit_outlined, color: ModuleColors.organisations, size: 22),
            SizedBox(height: 4),
            Text('Modifier', style: TextStyle(fontSize: 10, fontWeight: FontWeight.w700, color: ModuleColors.organisations)),
          ],
        ),
      ),
      secondaryBackground: Container(
        margin: const EdgeInsets.symmetric(vertical: 1),
        decoration: BoxDecoration(
          color: AppColors.error.withOpacity(0.13),
          borderRadius: BorderRadius.circular(8),
        ),
        alignment: Alignment.centerRight,
        padding: const EdgeInsets.symmetric(horizontal: 20),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(Icons.delete_outline, color: AppColors.error, size: 22),
            const SizedBox(height: 4),
            Text('Supprimer', style: TextStyle(fontSize: 10, fontWeight: FontWeight.w700, color: AppColors.error)),
          ],
        ),
      ),
      child: OrganizationCard(
        organization: org,
        onTap: () => _showOrganizationDetails(org),
        onEdit: () => _showEditOrganizationDialog(org),
        onDelete: () => _confirmDeleteOrganization(org),
        showActions: canManage,
      ),
    );
  }

  Widget _buildLoadingMorePlaceholder(BuildContext context, List<OrganizationModel> orgs) {
    return ListView.separated(
      shrinkWrap: true,
      physics: const NeverScrollableScrollPhysics(),
      itemCount: orgs.length,
      separatorBuilder: (_, __) => const SizedBox(height: SpacingTokens.sm),
      itemBuilder: (context, i) => OrganizationCard(organization: orgs[i], onTap: () => _showOrganizationDetails(orgs[i]), showActions: false),
    );
  }

  // ─── FAB ──────────────────────────────────────────────────────────────────

  Widget? _buildActionButton(BuildContext context, OrganizationsState state) {
    // Afficher le FAB si on a des données (état direct ou cache)
    final hasData = state is OrganizationsLoaded ||
        state is OrganizationsLoadingMore ||
        _cachedListState != null;
    if (!hasData) return null;
    final authState = context.read<AuthBloc>().state;
    if (authState is! AuthAuthenticated || authState.effectiveRole != UserRole.superAdmin) return null;

    return FloatingActionButton(
      onPressed: _showCreateOrganizationDialog,
      backgroundColor: ModuleColors.organisations,
      foregroundColor: AppColors.onPrimary,
      elevation: 6,
      tooltip: 'Nouvelle organisation',
      child: const Icon(Icons.add),
    );
  }

  // ─── Empty state ──────────────────────────────────────────────────────────

  Widget _buildEmptyState(BuildContext context) {
    return Center(
      child: Padding(
        padding: const EdgeInsets.all(SpacingTokens.xl),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              padding: const EdgeInsets.all(SpacingTokens.xl),
              decoration: BoxDecoration(color: ModuleColors.organisations.withOpacity(0.08), shape: BoxShape.circle),
              child: const Icon(Icons.business_outlined, size: 56, color: ModuleColors.organisations),
            ),
            const SizedBox(height: SpacingTokens.lg),
            Text(
              'Aucune organisation trouvée',
              style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: Theme.of(context).colorScheme.onSurface),
            ),
            const SizedBox(height: SpacingTokens.xs),
            Text(
              'Modifiez vos critères de recherche\nou créez une nouvelle organisation.',
              style: TextStyle(fontSize: 14, color: Theme.of(context).colorScheme.onSurfaceVariant, height: 1.5),
              textAlign: TextAlign.center,
            ),
            const SizedBox(height: SpacingTokens.lg),
            FilledButton.icon(
              onPressed: () {
                context.read<OrganizationsBloc>().add(const ClearOrganizationsFilters());
                _searchController.clear();
              },
              icon: const Icon(Icons.filter_list_off, size: 18),
              label: const Text('Réinitialiser les filtres'),
              style: FilledButton.styleFrom(backgroundColor: ModuleColors.organisations),
            ),
          ],
        ),
      ),
    );
  }

  // ─── Loading state ────────────────────────────────────────────────────────

  Widget _buildLoadingState(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          const CircularProgressIndicator(color: ModuleColors.organisations, strokeWidth: 3),
          const SizedBox(height: SpacingTokens.md),
          Text(
            'Chargement des organisations...',
            style: TextStyle(fontSize: 14, color: Theme.of(context).colorScheme.onSurfaceVariant),
          ),
        ],
      ),
    );
  }

  // ─── Error state ──────────────────────────────────────────────────────────

  Widget _buildErrorState(BuildContext context, OrganizationsError state) {
    final cs = Theme.of(context).colorScheme;
    return Center(
      child: Container(
        margin: const EdgeInsets.all(SpacingTokens.xl),
        padding: const EdgeInsets.all(SpacingTokens.xl),
        decoration: BoxDecoration(
          color: cs.errorContainer.withOpacity(0.3),
          borderRadius: BorderRadius.circular(RadiusTokens.lg),
          border: Border.all(color: cs.error.withOpacity(0.3), width: 1),
        ),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(Icons.error_outline, size: 56, color: cs.error),
            const SizedBox(height: SpacingTokens.md),
            Text(
              state.message,
              style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: cs.onSurface),
              textAlign: TextAlign.center,
            ),
            if (state.details != null) ...[
              const SizedBox(height: SpacingTokens.xs),
              Text(state.details!, style: TextStyle(fontSize: 12, color: cs.onSurfaceVariant), textAlign: TextAlign.center),
            ],
            const SizedBox(height: SpacingTokens.lg),
            FilledButton.icon(
              onPressed: () => context.read<OrganizationsBloc>().add(const LoadOrganizations(refresh: true)),
              icon: const Icon(Icons.refresh, size: 18),
              label: const Text('Réessayer'),
              style: FilledButton.styleFrom(backgroundColor: ModuleColors.organisations),
            ),
          ],
        ),
      ),
    );
  }

  // ─── Actions ──────────────────────────────────────────────────────────────

  void _showOrganizationDetails(OrganizationModel org) {
    final orgId = org.id;
    if (orgId == null || orgId.isEmpty) return;
    final bloc = context.read<OrganizationsBloc>();
    Navigator.of(context).push(MaterialPageRoute<void>(
      builder: (_) => BlocProvider.value(value: bloc, child: OrganizationDetailPage(organizationId: orgId)),
    ));
  }

  void _showCreateOrganizationDialog() {
    final bloc = context.read<OrganizationsBloc>();
    showDialog(
      context: context,
      builder: (_) => BlocProvider.value(value: bloc, child: const CreateOrganizationDialog()),
    );
  }

  void _showEditOrganizationDialog(OrganizationModel org) {
    final bloc = context.read<OrganizationsBloc>();
    showDialog(
      context: context,
      builder: (_) => BlocProvider.value(value: bloc, child: EditOrganizationDialog(organization: org)),
    );
  }

  void _confirmDeleteOrganization(OrganizationModel org) {
    final bloc = context.read<OrganizationsBloc>();
    showDialog(
      context: context,
      builder: (ctx) => AlertDialog(
        title: const Text('Supprimer l\'organisation'),
        content: Text('Voulez-vous vraiment supprimer "${org.nom}" ?'),
        actions: [
          TextButton(onPressed: () => Navigator.of(ctx).pop(), child: const Text('Annuler')),
          FilledButton(
            onPressed: () {
              if (org.id != null) bloc.add(DeleteOrganization(org.id!));
              Navigator.of(ctx).pop();
            },
            style: FilledButton.styleFrom(backgroundColor: Theme.of(context).colorScheme.error, foregroundColor: AppColors.onError),
            child: const Text('Supprimer'),
          ),
        ],
      ),
    );
  }
}
