import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:provider/provider.dart';

import '../../../config/injection/injection.dart';
import '../../../core/constants/design_system.dart';
import '../../../core/utils/app_logger.dart';
import '../../../data/providers/presence_provider.dart';
import '../../../data/services/chat_websocket_service.dart';
import '../../../data/services/secure_storage.dart';
import '../../../domain/entities/chat_message.dart';
import '../../../domain/entities/conversation.dart';
import '../../state_management/chat_bloc.dart';
import '../../widgets/custom_snackbar.dart';
import '../../widgets/date_separator.dart';
import '../../widgets/message_bubble.dart';
import '../../widgets/shimmer_loading.dart';
import '../../widgets/typing_indicator_widget.dart';

/// Écran de chat pour une conversation individuelle.
class ChatScreen extends StatelessWidget {
  const ChatScreen({
    required this.conversation,
    super.key,
  });

  final Conversation conversation;

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => sl<ChatBloc>(),
      child: _ChatScreenContent(conversation: conversation),
    );
  }
}

class _ChatScreenContent extends StatefulWidget {
  const _ChatScreenContent({required this.conversation});

  final Conversation conversation;

  @override
  State<_ChatScreenContent> createState() => _ChatScreenContentState();
}

class _ChatScreenContentState extends State<_ChatScreenContent> {
  final SecureStorage _storage = SecureStorage();
  late ChatWebSocketService _wsService;
  final TextEditingController _messageController = TextEditingController();
  final ScrollController _scrollController = ScrollController();

  String? _currentUserId;
  bool _isTyping = false;
  Timer? _typingTimer;

  StreamSubscription<ChatMessage>? _messageSubscription;
  StreamSubscription<TypingIndicator>? _typingSubscription;
  StreamSubscription<DeliveryConfirmation>? _deliverySubscription;

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

  @override
  void dispose() {
    _messageController.dispose();
    _scrollController.dispose();
    _typingTimer?.cancel();
    _messageSubscription?.cancel();
    _typingSubscription?.cancel();
    _deliverySubscription?.cancel();
    _wsService.dispose();
    super.dispose();
  }

  Future<void> _initializeChat() async {
    _currentUserId = await _storage.getUserId();
    if (_currentUserId == null) return;

    // Créer une nouvelle instance du WebSocket service
    _wsService = ChatWebSocketService(_currentUserId!);

    // Se connecter au WebSocket
    await _wsService.connect();

    // S'abonner aux nouveaux messages
    _messageSubscription = _wsService.messageStream.listen((message) {
      if (message.conversationId == widget.conversation.id) {
        // Ajouter le message au Bloc
        if (mounted) {
          context.read<ChatBloc>().add(AddMessageToConversation(message));
        }
        _scrollToBottom();

        // Marquer comme lu si ce n'est pas notre message
        if (message.senderId != _currentUserId) {
          _markAsRead(message.id);
        }
      }
    });

    // S'abonner aux indicateurs de frappe
    _typingSubscription = _wsService.typingStream.listen((indicator) {
      if (indicator.conversationId == widget.conversation.id &&
          indicator.userId != _currentUserId) {
        if (mounted) {
          setState(() {
            _isTyping = indicator.isTyping;
          });
        }
      }
    });

    // S'abonner aux confirmations de délivrance
    _deliverySubscription = _wsService.deliveryStream.listen((confirmation) {
      AppLogger.d('Delivery confirmation reçue: ${confirmation.messageId}', tag: 'ChatScreen');
      if (mounted) {
        AppLogger.d('Envoi MarkMessageAsDelivered au ChatBloc', tag: 'ChatScreen');
        context.read<ChatBloc>().add(MarkMessageAsDelivered(confirmation.messageId));
      }
    });

    // Charger les messages via le Bloc
    if (mounted) {
      context.read<ChatBloc>().add(LoadMessages(conversationId: widget.conversation.id));
    }
  }

  void _sendMessage() {
    final content = _messageController.text.trim();
    if (content.isEmpty || _currentUserId == null) return;

    _messageController.clear();

    // Arrêter l'indicateur de frappe
    _wsService.sendTypingIndicator(widget.conversation.id, false);

    // Envoyer via le Bloc
    context.read<ChatBloc>().add(SendMessage(
          senderId: _currentUserId!,
          recipientId: widget.conversation.participantId,
          content: content,
        ));

    _scrollToBottom();
  }

  void _markAsRead(String messageId) {
    context.read<ChatBloc>().add(MarkMessageAsRead(messageId));
    _wsService.sendReadReceipt(messageId);
  }

  void _onTextChanged(String text) {
    // Envoyer l'indicateur de frappe après 500ms d'inactivité
    _typingTimer?.cancel();

    if (text.isNotEmpty) {
      _wsService.sendTypingIndicator(widget.conversation.id, true);

      _typingTimer = Timer(const Duration(milliseconds: 1500), () {
        _wsService.sendTypingIndicator(widget.conversation.id, false);
      });
    } else {
      _wsService.sendTypingIndicator(widget.conversation.id, false);
    }
  }

  void _scrollToBottom() {
    if (_scrollController.hasClients) {
      Future.delayed(const Duration(milliseconds: 100), () {
        if (_scrollController.hasClients) {
          _scrollController.animateTo(
            0,
            duration: const Duration(milliseconds: 300),
            curve: Curves.easeOut,
          );
        }
      });
    }
  }

  /// Vérifie si deux dates sont le même jour.
  bool _isSameDay(DateTime date1, DateTime date2) {
    return date1.year == date2.year &&
        date1.month == date2.month &&
        date1.day == date2.day;
  }

  /// Calcule le nombre total d'items (messages + séparateurs).
  int _getTotalItemCount(List<ChatMessage> messages) {
    if (messages.isEmpty) return 0;

    int separatorCount = 0;
    DateTime? lastDate;

    for (var message in messages) {
      final messageDate = DateTime(
        message.timestamp.year,
        message.timestamp.month,
        message.timestamp.day,
      );

      if (lastDate == null || !_isSameDay(lastDate, messageDate)) {
        separatorCount++;
        lastDate = messageDate;
      }
    }

    return messages.length + separatorCount;
  }

  /// Détermine si l'index donné correspond à un séparateur de date.
  bool _isDateSeparatorAtIndex(int displayIndex, List<ChatMessage> messages) {
    if (messages.isEmpty) return false;

    int itemsProcessed = 0;
    DateTime? lastDate;

    for (int i = 0; i < messages.length; i++) {
      final messageDate = DateTime(
        messages[i].timestamp.year,
        messages[i].timestamp.month,
        messages[i].timestamp.day,
      );

      if (lastDate == null || !_isSameDay(lastDate, messageDate)) {
        if (itemsProcessed == displayIndex) {
          return true; // C'est un séparateur
        }
        itemsProcessed++;
        lastDate = messageDate;
      }

      if (itemsProcessed == displayIndex) {
        return false; // C'est un message
      }
      itemsProcessed++;
    }

    return false;
  }

  /// Obtient l'index réel du message en tenant compte des séparateurs.
  int _getMessageIndex(int displayIndex, List<ChatMessage> messages) {
    if (messages.isEmpty) return 0;

    int itemsProcessed = 0;
    int messageIndex = 0;
    DateTime? lastDate;

    for (int i = 0; i < messages.length; i++) {
      final messageDate = DateTime(
        messages[i].timestamp.year,
        messages[i].timestamp.month,
        messages[i].timestamp.day,
      );

      if (lastDate == null || !_isSameDay(lastDate, messageDate)) {
        if (itemsProcessed == displayIndex) {
          return i; // On retourne l'index du premier message de ce groupe
        }
        itemsProcessed++;
        lastDate = messageDate;
      }

      if (itemsProcessed == displayIndex) {
        return i;
      }
      itemsProcessed++;
    }

    return messageIndex;
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);

    return Scaffold(
      appBar: AppBar(
        title: Row(
          children: [
            Hero(
              tag: 'chat_avatar_${widget.conversation.participantId}',
              child: CircleAvatar(
                radius: 18,
                backgroundImage: widget.conversation.participantProfileImageUrl != null
                    ? NetworkImage(widget.conversation.participantProfileImageUrl!)
                    : null,
                child: widget.conversation.participantProfileImageUrl == null
                    ? Text(
                        widget.conversation.participantFirstName[0].toUpperCase(),
                        style: const TextStyle(fontSize: 16),
                      )
                    : null,
              ),
            ),
            const SizedBox(width: DesignSystem.spacingSm),
            Expanded(
              child: Consumer<PresenceProvider>(
                builder: (context, presenceProvider, child) {
                  final isOnline = presenceProvider.isUserOnline(widget.conversation.participantId);

                  return Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        widget.conversation.participantFullName,
                        style: theme.textTheme.titleMedium?.copyWith(
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                      if (_isTyping)
                        Text(
                          'En train d\'écrire...',
                          style: theme.textTheme.bodySmall?.copyWith(
                            color: theme.colorScheme.primary,
                            fontStyle: FontStyle.italic,
                          ),
                        )
                      else
                        Text(
                          isOnline ? 'En ligne' : 'Hors ligne',
                          style: theme.textTheme.bodySmall?.copyWith(
                            color: isOnline ? Colors.green : Colors.grey,
                          ),
                        ),
                    ],
                  );
                },
              ),
            ),
          ],
        ),
      ),
      body: BlocConsumer<ChatBloc, ChatState>(
        listener: (context, state) {
          if (state.messagesStatus == MessagesStatus.error) {
            context.showError(state.errorMessage ?? 'Erreur de chargement');
          }
          if (state.sendMessageStatus == SendMessageStatus.error) {
            context.showError(state.errorMessage ?? 'Erreur d\'envoi');
          }
          if (state.sendMessageStatus == SendMessageStatus.success) {
            _scrollToBottom();
          }
        },
        builder: (context, state) {
          return Column(
            children: [
              // Liste des messages
              Expanded(
                child: state.messagesStatus == MessagesStatus.loading
                    ? const SkeletonList(
                        itemCount: 10,
                        skeletonWidget: ListItemSkeleton(),
                      )
                    : state.messagesStatus == MessagesStatus.error
                        ? _buildErrorState(theme, state.errorMessage)
                        : state.messages.isEmpty
                            ? _buildEmptyState(theme)
                            : ListView.builder(
                                controller: _scrollController,
                                reverse: true,
                                padding: const EdgeInsets.all(DesignSystem.spacingLg),
                                itemCount: _getTotalItemCount(state.messages) + (_isTyping ? 1 : 0),
                                itemBuilder: (context, index) {
                                  // Afficher l'indicateur de frappe en premier (index 0)
                                  if (_isTyping && index == 0) {
                                    return const Padding(
                                      padding: EdgeInsets.only(bottom: DesignSystem.spacingSm),
                                      child: TypingIndicatorWidget(),
                                    );
                                  }

                                  final actualIndex = _isTyping ? index - 1 : index;

                                  // Vérifier si c'est un séparateur de date
                                  if (_isDateSeparatorAtIndex(actualIndex, state.messages)) {
                                    final messageIndex = _getMessageIndex(actualIndex, state.messages);
                                    final message = state.messages[messageIndex];
                                    return DateSeparator(date: message.timestamp);
                                  }

                                  // C'est un message normal
                                  final messageIndex = _getMessageIndex(actualIndex, state.messages);
                                  final message = state.messages[messageIndex];
                                  final isCurrentUser = message.senderId == _currentUserId;

                                  return MessageBubble(
                                    message: message,
                                    isCurrentUser: isCurrentUser,
                                  );
                                },
                              ),
              ),

              // Barre de saisie
              Container(
                padding: EdgeInsets.only(
                  left: DesignSystem.spacingLg,
                  right: DesignSystem.spacingLg,
                  top: DesignSystem.spacingSm,
                  bottom: MediaQuery.of(context).viewInsets.bottom + DesignSystem.spacingSm,
                ),
                decoration: BoxDecoration(
                  color: theme.scaffoldBackgroundColor,
                  border: Border(
                    top: BorderSide(color: theme.dividerColor),
                  ),
                ),
                child: Row(
                  children: [
                    Expanded(
                      child: TextField(
                        controller: _messageController,
                        onChanged: _onTextChanged,
                        decoration: InputDecoration(
                          hintText: 'Écrivez un message...',
                          border: OutlineInputBorder(
                            borderRadius: BorderRadius.circular(DesignSystem.radiusLg),
                          ),
                          contentPadding: const EdgeInsets.symmetric(
                            horizontal: DesignSystem.spacingLg,
                            vertical: DesignSystem.spacingSm,
                          ),
                        ),
                        maxLines: null,
                        textInputAction: TextInputAction.send,
                        onSubmitted: (_) => _sendMessage(),
                      ),
                    ),
                    const SizedBox(width: DesignSystem.spacingSm),
                    state.sendMessageStatus == SendMessageStatus.sending
                        ? const Padding(
                            padding: EdgeInsets.all(8.0),
                            child: SizedBox(
                              width: 24,
                              height: 24,
                              child: CircularProgressIndicator(strokeWidth: 2),
                            ),
                          )
                        : IconButton(
                            onPressed: _sendMessage,
                            icon: const Icon(Icons.send),
                            color: theme.colorScheme.primary,
                            iconSize: 28,
                          ),
                  ],
                ),
              ),
            ],
          );
        },
      ),
    );
  }

  Widget _buildErrorState(ThemeData theme, String? errorMessage) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.error_outline, size: 64, color: Colors.grey[400]),
          const SizedBox(height: DesignSystem.spacingLg),
          Text('Erreur de chargement', style: theme.textTheme.titleLarge),
          const SizedBox(height: DesignSystem.spacingSm),
          Text(
            errorMessage ?? 'Une erreur est survenue',
            style: theme.textTheme.bodyMedium,
            textAlign: TextAlign.center,
          ),
          const SizedBox(height: DesignSystem.spacingXl),
          ElevatedButton.icon(
            onPressed: () {
              context.read<ChatBloc>().add(LoadMessages(conversationId: widget.conversation.id));
            },
            icon: const Icon(Icons.refresh),
            label: const Text('Réessayer'),
          ),
        ],
      ),
    );
  }

  Widget _buildEmptyState(ThemeData theme) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.chat_bubble_outline, size: 64, color: Colors.grey[400]),
          const SizedBox(height: DesignSystem.spacingLg),
          Text(
            'Aucun message',
            style: theme.textTheme.titleLarge,
          ),
          const SizedBox(height: DesignSystem.spacingSm),
          Text(
            'Envoyez le premier message !',
            style: theme.textTheme.bodyMedium?.copyWith(
              color: Colors.grey[600],
            ),
          ),
        ],
      ),
    );
  }
}
