/// Widget adaptatif révolutionnaire avec morphing intelligent
/// Transformation dynamique selon le rôle utilisateur avec animations fluides
library adaptive_widget;

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../features/authentication/data/models/user.dart';
import '../../features/authentication/data/models/user_role.dart';
import '../../features/authentication/data/datasources/permission_engine.dart';
import '../../features/authentication/presentation/bloc/auth_bloc.dart';

/// Widget adaptatif révolutionnaire qui se transforme selon le rôle utilisateur
/// 
/// Fonctionnalités :
/// - Morphing intelligent avec animations fluides
/// - Widgets spécifiques par rôle
/// - Vérification de permissions intégrée
/// - Fallback gracieux pour les rôles non supportés
/// - Cache des widgets pour les performances
class AdaptiveWidget extends StatefulWidget {
  /// Widgets spécifiques par rôle utilisateur
  final Map<UserRole, Widget Function()> roleWidgets;
  
  /// Permissions requises pour afficher le widget
  final List<String> requiredPermissions;
  
  /// Widget affiché si les permissions sont insuffisantes
  final Widget? fallbackWidget;
  
  /// Widget affiché pendant le chargement
  final Widget? loadingWidget;
  
  /// Activer les animations de morphing
  final bool enableMorphing;
  
  /// Durée de l'animation de morphing
  final Duration morphingDuration;
  
  /// Courbe d'animation
  final Curve animationCurve;
  
  /// Contexte organisationnel pour les permissions
  final String? organizationId;
  
  /// Activer l'audit trail
  final bool auditLog;

  /// Constructeur du widget adaptatif
  const AdaptiveWidget({
    super.key,
    required this.roleWidgets,
    this.requiredPermissions = const [],
    this.fallbackWidget,
    this.loadingWidget,
    this.enableMorphing = true,
    this.morphingDuration = const Duration(milliseconds: 800),
    this.animationCurve = Curves.easeInOutCubic,
    this.organizationId,
    this.auditLog = true,
  });

  @override
  State<AdaptiveWidget> createState() => _AdaptiveWidgetState();
}

class _AdaptiveWidgetState extends State<AdaptiveWidget>
    with TickerProviderStateMixin {
  
  /// Cache des widgets construits pour éviter les reconstructions
  final Map<UserRole, Widget> _widgetCache = {};
  
  /// Contrôleur d'animation pour le morphing
  late AnimationController _morphController;
  
  /// Animation d'opacité
  late Animation<double> _opacityAnimation;
  
  /// Animation d'échelle
  late Animation<double> _scaleAnimation;
  
  /// Rôle utilisateur précédent pour détecter les changements
  UserRole? _previousRole;

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

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

  /// Initialise les animations de morphing
  void _initializeAnimations() {
    _morphController = AnimationController(
      duration: widget.morphingDuration,
      vsync: this,
    );
    
    _opacityAnimation = Tween<double>(
      begin: 0.0,
      end: 1.0,
    ).animate(CurvedAnimation(
      parent: _morphController,
      curve: widget.animationCurve,
    ));
    
    _scaleAnimation = Tween<double>(
      begin: 0.95,
      end: 1.0,
    ).animate(CurvedAnimation(
      parent: _morphController,
      curve: widget.animationCurve,
    ));
    
    // Démarrer l'animation initiale
    _morphController.forward();
  }

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<AuthBloc, AuthState>(
      builder: (context, state) {
        // État de chargement
        if (state is AuthLoading) {
          return widget.loadingWidget ?? _buildLoadingWidget();
        }
        
        // État non authentifié
        if (state is! AuthAuthenticated) {
          return _buildForRole(UserRole.visitor);
        }
        
        final user = state.user;
        final currentRole = user.primaryRole;
        
        // Détecter le changement de rôle pour déclencher l'animation
        if (_previousRole != null && _previousRole != currentRole && widget.enableMorphing) {
          _triggerMorphing();
        }
        _previousRole = currentRole;
        
        return FutureBuilder<bool>(
          future: _checkPermissions(user),
          builder: (context, permissionSnapshot) {
            if (permissionSnapshot.connectionState == ConnectionState.waiting) {
              return widget.loadingWidget ?? _buildLoadingWidget();
            }
            
            final hasPermissions = permissionSnapshot.data ?? false;
            if (!hasPermissions) {
              return widget.fallbackWidget ?? _buildUnauthorizedWidget();
            }
            
            return _buildForRole(currentRole);
          },
        );
      },
    );
  }

  /// Construit le widget pour un rôle spécifique
  Widget _buildForRole(UserRole role) {
    // Vérifier le cache
    if (_widgetCache.containsKey(role)) {
      return _wrapWithAnimation(_widgetCache[role]!);
    }
    
    // Trouver le widget approprié
    Widget? widget = _findWidgetForRole(role);
    
    widget ??= this.widget.fallbackWidget ?? _buildUnsupportedRoleWidget(role);
    
    // Mettre en cache
    _widgetCache[role] = widget;
    
    return _wrapWithAnimation(widget);
  }

  /// Trouve le widget approprié pour un rôle
  Widget? _findWidgetForRole(UserRole role) {
    // Vérification directe
    if (widget.roleWidgets.containsKey(role)) {
      return widget.roleWidgets[role]!();
    }
    
    // Recherche du meilleur match par niveau de rôle
    UserRole? bestMatch;
    for (final availableRole in widget.roleWidgets.keys) {
      if (availableRole.level <= role.level) {
        if (bestMatch == null || availableRole.level > bestMatch.level) {
          bestMatch = availableRole;
        }
      }
    }
    
    return bestMatch != null ? widget.roleWidgets[bestMatch]!() : null;
  }

  /// Enveloppe le widget avec les animations
  Widget _wrapWithAnimation(Widget child) {
    if (!widget.enableMorphing) return child;
    
    return AnimatedBuilder(
      animation: _morphController,
      builder: (context, _) {
        return Transform.scale(
          scale: _scaleAnimation.value,
          child: Opacity(
            opacity: _opacityAnimation.value,
            child: child,
          ),
        );
      },
    );
  }

  /// Déclenche l'animation de morphing
  void _triggerMorphing() {
    _morphController.reset();
    _morphController.forward();
    
    // Vider le cache pour forcer la reconstruction
    _widgetCache.clear();
  }

  /// Vérifie les permissions requises
  Future<bool> _checkPermissions(User user) async {
    if (widget.requiredPermissions.isEmpty) return true;
    
    final results = await PermissionEngine.hasPermissions(
      user,
      widget.requiredPermissions,
      organizationId: widget.organizationId,
      auditLog: widget.auditLog,
    );
    
    return results.values.every((hasPermission) => hasPermission);
  }

  /// Widget de chargement par défaut
  Widget _buildLoadingWidget() {
    return const Center(
      child: SizedBox(
        width: 24,
        height: 24,
        child: CircularProgressIndicator(strokeWidth: 2),
      ),
    );
  }

  /// Widget non autorisé par défaut
  Widget _buildUnauthorizedWidget() {
    return Container(
      padding: const EdgeInsets.all(16),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(
            Icons.lock_outline,
            size: 48,
            color: Theme.of(context).disabledColor,
          ),
          const SizedBox(height: 8),
          Text(
            'Accès non autorisé',
            style: Theme.of(context).textTheme.titleMedium?.copyWith(
              color: Theme.of(context).disabledColor,
            ),
          ),
          const SizedBox(height: 4),
          Text(
            'Vous n\'avez pas les permissions nécessaires',
            style: Theme.of(context).textTheme.bodySmall?.copyWith(
              color: Theme.of(context).disabledColor,
            ),
            textAlign: TextAlign.center,
          ),
        ],
      ),
    );
  }

  /// Widget pour rôle non supporté
  Widget _buildUnsupportedRoleWidget(UserRole role) {
    return Container(
      padding: const EdgeInsets.all(16),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(
            Icons.warning_outlined,
            size: 48,
            color: Theme.of(context).colorScheme.error,
          ),
          const SizedBox(height: 8),
          Text(
            'Rôle non supporté',
            style: Theme.of(context).textTheme.titleMedium?.copyWith(
              color: Theme.of(context).colorScheme.error,
            ),
          ),
          const SizedBox(height: 4),
          Text(
            'Le rôle ${role.displayName} n\'est pas supporté par ce widget',
            style: Theme.of(context).textTheme.bodySmall,
            textAlign: TextAlign.center,
          ),
        ],
      ),
    );
  }
}

/// Widget sécurisé avec vérification de permissions intégrée
/// 
/// Version simplifiée d'AdaptiveWidget pour les cas où seules
/// les permissions importent, pas le rôle spécifique
class SecureWidget extends StatelessWidget {
  /// Permissions requises pour afficher le widget
  final List<String> requiredPermissions;
  
  /// Widget à afficher si autorisé
  final Widget child;
  
  /// Widget à afficher si non autorisé
  final Widget? unauthorizedWidget;
  
  /// Widget à afficher pendant le chargement
  final Widget? loadingWidget;
  
  /// Contexte organisationnel
  final String? organizationId;
  
  /// Activer l'audit trail
  final bool auditLog;

  /// Constructeur du widget sécurisé
  const SecureWidget({
    super.key,
    required this.requiredPermissions,
    required this.child,
    this.unauthorizedWidget,
    this.loadingWidget,
    this.organizationId,
    this.auditLog = true,
  });

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<AuthBloc, AuthState>(
      builder: (context, state) {
        if (state is AuthLoading) {
          return loadingWidget ?? const SizedBox.shrink();
        }
        
        if (state is! AuthAuthenticated) {
          return unauthorizedWidget ?? const SizedBox.shrink();
        }
        
        return FutureBuilder<bool>(
          future: _checkPermissions(state.user),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return loadingWidget ?? const SizedBox.shrink();
            }
            
            final hasPermissions = snapshot.data ?? false;
            if (!hasPermissions) {
              return unauthorizedWidget ?? const SizedBox.shrink();
            }
            
            return child;
          },
        );
      },
    );
  }

  /// Vérifie les permissions requises
  Future<bool> _checkPermissions(User user) async {
    if (requiredPermissions.isEmpty) return true;
    
    final results = await PermissionEngine.hasPermissions(
      user,
      requiredPermissions,
      organizationId: organizationId,
      auditLog: auditLog,
    );
    
    return results.values.every((hasPermission) => hasPermission);
  }
}
