import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'dart:async';
import '../../blocs/user/user_bloc.dart';
import '../../blocs/user/user_state.dart' as user_state;
import '../../blocs/message/message_bloc.dart';
import '../../blocs/message/message_event.dart';
import '../../blocs/message/message_state.dart';
import '../../models/group.dart';
import '../../models/group_member.dart';
import '../../models/message.dart';
import '../../repositories/group_repository.dart';
import '../../services/error_service.dart';

/// Chat group content widget for group messaging functionality.
///
/// This widget provides a complete chat interface for group members to
/// communicate within a travel group. Features include:
/// - Real-time message loading and sending
/// - Message editing and deletion
/// - Message reactions (like/unlike)
/// - Scroll-to-bottom functionality
/// - Message status indicators
///
/// The widget integrates with MessageBloc for state management and
/// handles various message operations through the bloc pattern.
class ChatGroupContent extends StatefulWidget {
  /// The group for which to display the chat interface
  final Group group;

  /// Creates a chat group content widget.
  ///
  /// Args:
  ///   [group]: The group object containing group details and ID
  const ChatGroupContent({super.key, required this.group});

  @override
  State<ChatGroupContent> createState() => _ChatGroupContentState();
}

class _ChatGroupContentState extends State<ChatGroupContent> {
  /// Controller for the message input field
  final _messageController = TextEditingController();

  /// Controller for managing scroll position in the message list
  final _scrollController = ScrollController();

  /// Currently selected message for editing (null if not editing)
  Message? _editingMessage;

  /// Repository pour gérer les groupes
  final _groupRepository = GroupRepository();

  /// Subscription pour écouter les changements des membres du groupe
  late StreamSubscription<List<GroupMember>> _membersSubscription;

  @override
  void initState() {
    super.initState();
    // Load messages when the widget initializes
    context.read<MessageBloc>().add(LoadMessages(widget.group.id));

    // Écouter les changements des membres du groupe
    _membersSubscription = _groupRepository
        .watchGroupMembers(widget.group.id)
        .listen((updatedMembers) {
          if (mounted) {
            setState(() {
              widget.group.members.clear();
              widget.group.members.addAll(updatedMembers);
            });
          }
        });
  }

  @override
  void dispose() {
    _messageController.dispose();
    _scrollController.dispose();
    _membersSubscription.cancel();
    super.dispose();
  }

  /// Sends a new message or updates an existing message.
  ///
  /// Handles both sending new messages and editing existing ones based
  /// on the current editing state. Validates input and clears the input
  /// field after successful submission.
  ///
  /// Args:
  ///   [currentUser]: The user sending or editing the message
  void _sendMessage(user_state.UserModel currentUser) {
    final messageText = _messageController.text.trim();
    if (messageText.isEmpty) return;

    if (_editingMessage != null) {
      // Edit mode - update existing message
      context.read<MessageBloc>().add(
        UpdateMessage(
          groupId: widget.group.id,
          messageId: _editingMessage!.id,
          newText: messageText,
        ),
      );
      _cancelEdit();
    } else {
      // Send mode - create new message
      context.read<MessageBloc>().add(
        SendMessage(
          groupId: widget.group.id,
          text: messageText,
          senderId: currentUser.id,
          senderName: currentUser.prenom,
        ),
      );
    }

    _messageController.clear();
  }

  /// Initiates editing mode for a selected message.
  ///
  /// Sets the message as the currently editing message and populates
  /// the input field with the message text for modification.
  ///
  /// Args:
  ///   [message]: The message to edit
  void _editMessage(Message message) {
    setState(() {
      _editingMessage = message;
      _messageController.text = message.text;
    });
  }

  /// Cancels the current editing operation.
  ///
  /// Resets the editing state and clears the input field,
  /// returning to normal message sending mode.
  void _cancelEdit() {
    setState(() {
      _editingMessage = null;
      _messageController.clear();
    });
  }

  /// Deletes a message from the group chat.
  ///
  /// Sends a delete event to the MessageBloc to remove the specified
  /// message from the group's message history.
  ///
  /// Args:
  ///   [messageId]: The ID of the message to delete
  void _deleteMessage(String messageId) {
    context.read<MessageBloc>().add(
      DeleteMessage(groupId: widget.group.id, messageId: messageId),
    );
  }

  void _reactToMessage(String messageId, String userId, String reaction) {
    context.read<MessageBloc>().add(
      ReactToMessage(
        groupId: widget.group.id,
        messageId: messageId,
        userId: userId,
        reaction: reaction,
      ),
    );
  }

  void _removeReaction(String messageId, String userId) {
    context.read<MessageBloc>().add(
      RemoveReaction(
        groupId: widget.group.id,
        messageId: messageId,
        userId: userId,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final isDark = Theme.of(context).brightness == Brightness.dark;

    return BlocBuilder<UserBloc, user_state.UserState>(
      builder: (context, userState) {
        if (userState is! user_state.UserLoaded) {
          return Scaffold(
            appBar: AppBar(title: Text(widget.group.name)),
            body: const Center(child: Text('Utilisateur non connecté')),
          );
        }

        final currentUser = userState.user;

        return Scaffold(
          appBar: AppBar(
            title: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(widget.group.name, style: const TextStyle(fontSize: 18)),
                Text(
                  '${widget.group.members.length} membre${widget.group.members.length > 1 ? 's' : ''}',
                  style: const TextStyle(
                    fontSize: 12,
                    fontWeight: FontWeight.normal,
                  ),
                ),
              ],
            ),
            actions: [
              IconButton(
                icon: const Icon(Icons.people),
                onPressed: () => _showMembersDialog(context),
              ),
            ],
          ),
          body: Column(
            children: [
              // Liste des messages
              Expanded(
                child: BlocConsumer<MessageBloc, MessageState>(
                  listener: (context, state) {
                    if (state is MessageError) {
                      ErrorService().showError(message: state.message);
                    }
                  },
                  builder: (context, state) {
                    if (state is MessageLoading) {
                      return const Center(child: CircularProgressIndicator());
                    }

                    if (state is MessagesLoaded) {
                      if (state.messages.isEmpty) {
                        return _buildEmptyState();
                      }

                      // Scroller automatiquement vers le bas au chargement
                      WidgetsBinding.instance.addPostFrameCallback((_) {
                        if (_scrollController.hasClients) {
                          _scrollController.jumpTo(
                            _scrollController.position.maxScrollExtent,
                          );
                        }
                      });

                      return ListView.builder(
                        controller: _scrollController,
                        padding: const EdgeInsets.all(16),
                        itemCount: state.messages.length,
                        itemBuilder: (context, index) {
                          final message = state.messages[index];
                          final isMe = message.senderId == currentUser.id;
                          final showDate =
                              index == 0 ||
                              !_isSameDay(
                                state.messages[index - 1].timestamp,
                                message.timestamp,
                              );

                          return Column(
                            children: [
                              if (showDate)
                                _buildDateSeparator(message.timestamp),
                              _buildMessageBubble(
                                message,
                                isMe,
                                isDark,
                                currentUser.id,
                              ),
                            ],
                          );
                        },
                      );
                    }

                    return _buildEmptyState();
                  },
                ),
              ),

              // Barre d'édition si un message est en cours de modification
              if (_editingMessage != null)
                Container(
                  color: isDark ? Colors.blue[900] : Colors.blue[100],
                  padding: const EdgeInsets.symmetric(
                    horizontal: 16,
                    vertical: 8,
                  ),
                  child: Row(
                    children: [
                      const Icon(Icons.edit, size: 20),
                      const SizedBox(width: 8),
                      const Expanded(child: Text('Modification du message')),
                      IconButton(
                        icon: const Icon(Icons.close),
                        onPressed: _cancelEdit,
                      ),
                    ],
                  ),
                ),

              // Zone de saisie
              Container(
                decoration: BoxDecoration(
                  color: Theme.of(context).scaffoldBackgroundColor,
                  border: Border(
                    top: BorderSide(
                      color: isDark ? Colors.grey[800]! : Colors.grey[300]!,
                      width: 1,
                    ),
                  ),
                ),
                padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8),
                child: SafeArea(
                  child: Row(
                    children: [
                      Expanded(
                        child: TextField(
                          controller: _messageController,
                          decoration: InputDecoration(
                            hintText: _editingMessage != null
                                ? 'Modifier le message...'
                                : 'Écrire un message...',
                            filled: true,
                            fillColor: isDark
                                ? Colors.grey[850]
                                : Colors.grey[100],
                            border: OutlineInputBorder(
                              borderRadius: BorderRadius.circular(24),
                              borderSide: BorderSide.none,
                            ),
                            contentPadding: const EdgeInsets.symmetric(
                              horizontal: 16,
                              vertical: 12,
                            ),
                          ),
                          maxLines: 5,
                          minLines: 1,
                          textCapitalization: TextCapitalization.sentences,
                        ),
                      ),
                      const SizedBox(width: 8),
                      IconButton(
                        onPressed: () => _sendMessage(currentUser),
                        icon: Icon(
                          _editingMessage != null ? Icons.check : Icons.send,
                        ),
                        style: IconButton.styleFrom(
                          backgroundColor: Theme.of(
                            context,
                          ).colorScheme.primary,
                          foregroundColor: Colors.white,
                          padding: const EdgeInsets.all(12),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ],
          ),
        );
      },
    );
  }

  Widget _buildEmptyState() {
    return Center(
      child: Padding(
        padding: const EdgeInsets.all(32),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(Icons.chat_bubble_outline, size: 80, color: Colors.grey[400]),
            const SizedBox(height: 16),
            const Text(
              'Aucun message',
              style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 8),
            Text(
              'Commencez la conversation !',
              textAlign: TextAlign.center,
              style: TextStyle(fontSize: 14, color: Colors.grey[600]),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildMessageBubble(
    Message message,
    bool isMe,
    bool isDark,
    String currentUserId,
  ) {
    final Color bubbleColor;
    final Color textColor;

    if (isMe) {
      bubbleColor = isDark ? const Color(0xFF1E3A5F) : const Color(0xFF90CAF9);
      textColor = isDark ? Colors.white : Colors.black87;
    } else {
      bubbleColor = isDark ? Colors.grey[800]! : Colors.grey[200]!;
      textColor = isDark ? Colors.white : Colors.black87;
    }

    // Trouver le membre qui a envoyé le message pour récupérer son pseudo actuel
    final senderMember = widget.group.members.cast<GroupMember?>().firstWhere(
      (m) => m?.userId == message.senderId,
      orElse: () => null,
    );

    // Utiliser le pseudo actuel du membre, ou le senderName en fallback
    final displayName = senderMember != null
        ? senderMember.pseudo
        : message.senderName;

    return Align(
      alignment: isMe ? Alignment.centerRight : Alignment.centerLeft,
      child: GestureDetector(
        onLongPress: () =>
            _showMessageOptions(context, message, isMe, currentUserId),
        child: Padding(
          padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
          child: Row(
            mainAxisAlignment: isMe
                ? MainAxisAlignment.end
                : MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.end,
            children: [
              // Avatar du sender (seulement pour les autres messages)
              if (!isMe) ...[
                CircleAvatar(
                  radius: 16,
                  backgroundImage:
                      (senderMember != null &&
                          senderMember.profilePictureUrl != null &&
                          senderMember.profilePictureUrl!.isNotEmpty)
                      ? NetworkImage(senderMember.profilePictureUrl!)
                      : null,
                  child:
                      (senderMember == null ||
                          senderMember.profilePictureUrl == null ||
                          senderMember.profilePictureUrl!.isEmpty)
                      ? Text(
                          displayName.isNotEmpty
                              ? displayName[0].toUpperCase()
                              : '?',
                          style: const TextStyle(fontSize: 12),
                        )
                      : null,
                ),
                const SizedBox(width: 8),
              ],

              Container(
                margin: const EdgeInsets.symmetric(vertical: 4),
                padding: const EdgeInsets.symmetric(
                  horizontal: 16,
                  vertical: 10,
                ),
                constraints: BoxConstraints(
                  maxWidth: MediaQuery.of(context).size.width * 0.65,
                ),
                decoration: BoxDecoration(
                  color: bubbleColor,
                  borderRadius: BorderRadius.only(
                    topLeft: const Radius.circular(16),
                    topRight: const Radius.circular(16),
                    bottomLeft: Radius.circular(isMe ? 16 : 4),
                    bottomRight: Radius.circular(isMe ? 4 : 16),
                  ),
                ),
                child: Column(
                  crossAxisAlignment: isMe
                      ? CrossAxisAlignment.end
                      : CrossAxisAlignment.start,
                  children: [
                    if (!isMe) ...[
                      Text(
                        displayName,
                        style: TextStyle(
                          fontSize: 12,
                          fontWeight: FontWeight.bold,
                          color: isDark ? Colors.grey[400] : Colors.grey[700],
                        ),
                      ),
                      const SizedBox(height: 4),
                    ],
                    Text(
                      message.isDeleted
                          ? 'a supprimé un message'
                          : message.text,
                      style: TextStyle(
                        fontSize: 15,
                        color: message.isDeleted
                            ? textColor.withValues(alpha: 0.5)
                            : textColor,
                        fontStyle: message.isDeleted
                            ? FontStyle.italic
                            : FontStyle.normal,
                      ),
                    ),
                    const SizedBox(height: 4),
                    Row(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        Text(
                          _formatTime(message.timestamp),
                          style: TextStyle(
                            fontSize: 11,
                            color: textColor.withValues(alpha: 0.7),
                          ),
                        ),
                        if (message.isEdited) ...[
                          const SizedBox(width: 4),
                          Text(
                            '(modifié)',
                            style: TextStyle(
                              fontSize: 10,
                              fontStyle: FontStyle.italic,
                              color: textColor.withValues(alpha: 0.6),
                            ),
                          ),
                        ],
                      ],
                    ),
                    // Afficher les réactions
                    if (message.reactions.isNotEmpty)
                      Padding(
                        padding: const EdgeInsets.only(top: 4),
                        child: Wrap(
                          spacing: 4,
                          children: _buildReactionChips(message, currentUserId),
                        ),
                      ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  List<Widget> _buildReactionChips(Message message, String currentUserId) {
    final reactionCounts = <String, List<String>>{};

    // Grouper les réactions par emoji
    message.reactions.forEach((userId, emoji) {
      reactionCounts.putIfAbsent(emoji, () => []).add(userId);
    });

    return reactionCounts.entries.map((entry) {
      final emoji = entry.key;
      final userIds = entry.value;
      final hasReacted = userIds.contains(currentUserId);

      return GestureDetector(
        onTap: () {
          if (hasReacted) {
            _removeReaction(message.id, currentUserId);
          } else {
            _reactToMessage(message.id, currentUserId, emoji);
          }
        },
        child: Container(
          padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
          decoration: BoxDecoration(
            color: hasReacted
                ? Colors.blue.withValues(alpha: 0.3)
                : Colors.grey.withValues(alpha: 0.3),
            borderRadius: BorderRadius.circular(12),
            border: hasReacted
                ? Border.all(color: Colors.blue, width: 1)
                : null,
          ),
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(emoji, style: const TextStyle(fontSize: 12)),
              const SizedBox(width: 2),
              Text(
                '${userIds.length}',
                style: const TextStyle(
                  fontSize: 10,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ],
          ),
        ),
      );
    }).toList();
  }

  void _showMessageOptions(
    BuildContext context,
    Message message,
    bool isMe,
    String currentUserId,
  ) {
    showModalBottomSheet(
      context: context,
      builder: (context) => SafeArea(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            // Réactions rapides
            Padding(
              padding: const EdgeInsets.all(16),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: ['👍', '❤️', '😂', '😮', '😢', '🔥'].map((emoji) {
                  return GestureDetector(
                    onTap: () {
                      Navigator.pop(context);
                      _reactToMessage(message.id, currentUserId, emoji);
                    },
                    child: Text(emoji, style: const TextStyle(fontSize: 32)),
                  );
                }).toList(),
              ),
            ),
            const Divider(height: 1),
            if (isMe) ...[
              ListTile(
                leading: const Icon(Icons.edit),
                title: const Text('Modifier'),
                onTap: () {
                  Navigator.pop(context);
                  _editMessage(message);
                },
              ),
              ListTile(
                leading: const Icon(Icons.delete, color: Colors.red),
                title: const Text(
                  'Supprimer',
                  style: TextStyle(color: Colors.red),
                ),
                onTap: () {
                  Navigator.pop(context);
                  _showDeleteConfirmation(context, message.id);
                },
              ),
            ],
            ListTile(
              leading: const Icon(Icons.close),
              title: const Text('Annuler'),
              onTap: () => Navigator.pop(context),
            ),
          ],
        ),
      ),
    );
  }

  void _showDeleteConfirmation(BuildContext context, String messageId) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Supprimer le message'),
        content: const Text('Êtes-vous sûr de vouloir supprimer ce message ?'),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('Annuler'),
          ),
          TextButton(
            onPressed: () {
              Navigator.pop(context);
              _deleteMessage(messageId);
            },
            style: TextButton.styleFrom(foregroundColor: Colors.red),
            child: const Text('Supprimer'),
          ),
        ],
      ),
    );
  }

  // Helpers pour les dates
  bool _isSameDay(DateTime date1, DateTime date2) {
    return date1.year == date2.year &&
        date1.month == date2.month &&
        date1.day == date2.day;
  }

  String _formatTime(DateTime date) {
    final hour = date.hour.toString().padLeft(2, '0');
    final minute = date.minute.toString().padLeft(2, '0');
    return '$hour:$minute';
  }

  String _formatDate(DateTime date) {
    final now = DateTime.now();
    final today = DateTime(now.year, now.month, now.day);
    final yesterday = today.subtract(const Duration(days: 1));
    final messageDate = DateTime(date.year, date.month, date.day);

    if (messageDate == today) {
      return 'Aujourd\'hui';
    } else if (messageDate == yesterday) {
      return 'Hier';
    } else {
      return '${date.day}/${date.month}/${date.year}';
    }
  }

  Widget _buildDateSeparator(DateTime date) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 16),
      child: Center(
        child: Container(
          padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
          decoration: BoxDecoration(
            color: Colors.grey.withValues(alpha: 0.3),
            borderRadius: BorderRadius.circular(12),
          ),
          child: Text(
            _formatDate(date),
            style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500),
          ),
        ),
      ),
    );
  }

  void _showMembersDialog(BuildContext context) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('Membres (${widget.group.members.length})'),
        content: SizedBox(
          width: double.maxFinite,
          child: ListView.builder(
            shrinkWrap: true,
            itemCount: widget.group.members.length,
            itemBuilder: (context, index) {
              final member = widget.group.members[index];
              final initials = member.pseudo.isNotEmpty
                  ? member.pseudo[0].toUpperCase()
                  : (member.firstName.isNotEmpty
                        ? member.firstName[0].toUpperCase()
                        : '?');

              // Construire le nom complet
              final fullName = '${member.firstName} ${member.lastName}'.trim();

              return ListTile(
                leading: CircleAvatar(
                  backgroundImage:
                      (member.profilePictureUrl != null &&
                          member.profilePictureUrl!.isNotEmpty)
                      ? NetworkImage(member.profilePictureUrl!)
                      : null,
                  child:
                      (member.profilePictureUrl == null ||
                          member.profilePictureUrl!.isEmpty)
                      ? Text(initials)
                      : null,
                ),
                title: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(member.pseudo),
                    if (fullName.isNotEmpty)
                      Text(
                        fullName,
                        style: const TextStyle(
                          fontSize: 12,
                          fontWeight: FontWeight.normal,
                        ),
                      ),
                  ],
                ),
                subtitle: member.role == 'admin'
                    ? const Text(
                        'Administrateur',
                        style: TextStyle(fontSize: 12),
                      )
                    : null,
                trailing: IconButton(
                  icon: const Icon(Icons.edit, size: 18),
                  onPressed: () {
                    Navigator.pop(context);
                    _showChangePseudoDialog(member);
                  },
                ),
              );
            },
          ),
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('Fermer'),
          ),
        ],
      ),
    );
  }

  void _showChangePseudoDialog(dynamic member) {
    final pseudoController = TextEditingController(text: member.pseudo);
    final theme = Theme.of(context);

    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        backgroundColor:
            theme.dialogTheme.backgroundColor ?? theme.colorScheme.surface,
        title: Text(
          'Changer le pseudo',
          style: theme.textTheme.titleLarge?.copyWith(
            color: theme.colorScheme.onSurface,
          ),
        ),
        content: TextField(
          controller: pseudoController,
          decoration: InputDecoration(
            hintText: 'Nouveau pseudo',
            border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
            contentPadding: const EdgeInsets.symmetric(
              horizontal: 16,
              vertical: 12,
            ),
          ),
          style: TextStyle(color: theme.colorScheme.onSurface),
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: Text(
              'Annuler',
              style: TextStyle(color: theme.colorScheme.primary),
            ),
          ),
          TextButton(
            onPressed: () {
              final newPseudo = pseudoController.text.trim();
              if (newPseudo.isNotEmpty) {
                _updateMemberPseudo(member, newPseudo);
                Navigator.pop(context);
              }
            },
            child: Text(
              'Valider',
              style: TextStyle(color: theme.colorScheme.primary),
            ),
          ),
        ],
      ),
    );
  }

  Future<void> _updateMemberPseudo(dynamic member, String newPseudo) async {
    try {
      final updatedMember = member.copyWith(pseudo: newPseudo);
      await _groupRepository.addMember(widget.group.id, updatedMember);

      if (mounted) {
        // Le stream listener va automatiquement mettre à jour les membres
        // Pas besoin de fermer le dialog ou de faire un refresh manuel

        ErrorService().showSnackbar(
          message: 'Pseudo modifié en "$newPseudo"',
          isError: false,
        );
      }
    } catch (e) {
      if (mounted) {
        ErrorService().showError(
          message: 'Erreur lors de la modification du pseudo: $e',
        );
      }
    }
  }
}
