import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:image/image.dart' as img;
import 'app_theme.dart';
import 'l10n/app_localizations.dart';
import 'l10n/localization_helpers.dart';
import 'app_state.dart';
import 'models/chat.dart';
import 'models/chat_message.dart';
import 'services/chat_service.dart';
import 'services/websocket_service.dart';
import 'services/notification_service.dart';
import 'widgets/chat_photo_dialog.dart';
import 'widgets/offline_banner.dart';

class ChatDetailsView extends StatefulWidget {
  final Chat chat;

  const ChatDetailsView({super.key, required this.chat});

  @override
  State<ChatDetailsView> createState() => _ChatDetailsViewState();
}

class _PreparedImage {
  const _PreparedImage({required this.base64DataUri, required this.bytes});

  final String base64DataUri;
  final Uint8List bytes;
}

class _ChatDetailsViewState extends State<ChatDetailsView> {
  final TextEditingController _messageController = TextEditingController();
  final ScrollController _scrollController = ScrollController();
  late List<ChatMessage> _messages;
  final WebSocketService _webSocketService = WebSocketService();
  StreamSubscription<List<Chat>>? _chatsStreamSubscription;
  String? _currentUserId;
  late final String _conversationKey;
  final ChatService _chatService = ChatService();
  final Map<String, Uint8List> _imageCache = <String, Uint8List>{};
  late Chat _activeChat;
  static const int _maxDisplayMessages = 30;

  @override
  void initState() {
    super.initState();
    _activeChat = widget.chat;
    _conversationKey = _activeChat.id;
    NotificationService().activeConversationKey = _conversationKey;
    _messages = _lastMessages(_activeChat.messages);
    _currentUserId = AppState().loggedInEmail;

    _chatsStreamSubscription = _chatService.chatsStream.listen(
      _handleChatsUpdate,
    );

    _chatService.initialize().then((_) async {
      _syncActiveChatFromService(replaceMessages: _messages.isEmpty);
      final history = await _chatService.loadMessagesForChat(_conversationKey);
      if (!mounted) return;
      if (history.isNotEmpty) {
        setState(() {
          _imageCache.clear();
          _messages = _lastMessages(history);
        });
        _scrollToBottom(immediate: true);
      }
      _syncActiveChatFromService();
      await _chatService.markConversationRead(_conversationKey);
    });

    // Scroll to bottom after initial build is complete
    _scrollToBottom(immediate: true);
  }

  @override
  void dispose() {
    if (NotificationService().activeConversationKey == _conversationKey) {
      NotificationService().activeConversationKey = null;
    }
    _chatsStreamSubscription?.cancel();
    _messageController.dispose();
    _scrollController.dispose();
    super.dispose();
  }

  void _scrollToBottom({bool immediate = false}) {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (!_scrollController.hasClients) {
        return;
      }
      final target = _scrollController.position.maxScrollExtent;
      if (immediate) {
        _scrollController.jumpTo(target);
      } else {
        _scrollController.animateTo(
          target,
          duration: const Duration(milliseconds: 250),
          curve: Curves.easeOut,
        );
      }
    });
  }

  void _handleChatsUpdate(List<Chat> chats) {
    if (!mounted) {
      return;
    }
    final updated = _findChatById(chats);
    if (updated == null) {
      return;
    }

    final shouldReplace = _shouldReplaceMessages(updated);

    setState(() {
      _activeChat = updated;
      if (shouldReplace) {
        _imageCache.clear();
        _messages = _lastMessages(updated.messages);
      }
    });

    if (shouldReplace) {
      _scrollToBottom();
      unawaited(_chatService.markConversationRead(_conversationKey));
    }
  }

  bool _shouldReplaceMessages(Chat chat) {
    if (chat.messages.length != _messages.length) {
      return true;
    }
    if (_messages.isEmpty) {
      return false;
    }
    final currentLast = _messages.last;
    final updatedLast = chat.messages.last;
    return currentLast.id != updatedLast.id ||
        currentLast.content != updatedLast.content ||
        currentLast.contentType != updatedLast.contentType;
  }

  List<ChatMessage> _lastMessages(List<ChatMessage> messages) {
    final sorted = List<ChatMessage>.from(messages)
      ..sort((a, b) => a.createdAt.compareTo(b.createdAt));
    if (sorted.length > _maxDisplayMessages) {
      return sorted.sublist(sorted.length - _maxDisplayMessages);
    }
    return sorted;
  }

  Chat? _findChatById(List<Chat> chats) {
    for (final chat in chats) {
      if (chat.id == _conversationKey) {
        return chat;
      }
    }
    return null;
  }

  void _syncActiveChatFromService({bool replaceMessages = false}) {
    final updated = _findChatById(_chatService.currentChats);
    if (updated == null || !mounted) {
      return;
    }

    final shouldReplace = replaceMessages || _shouldReplaceMessages(updated);

    setState(() {
      _activeChat = updated;
      if (shouldReplace) {
        _imageCache.clear();
        _messages = _lastMessages(updated.messages);
      }
    });

    if (shouldReplace) {
      _scrollToBottom();
      unawaited(_chatService.markConversationRead(_conversationKey));
    }
  }

  Future<void> _sendMessage() async {
    final text = _messageController.text.trim();
    if (text.isEmpty) {
      return;
    }

    final sender = _currentUserId;
    final receiver = _activeChat.receiver;

    if (sender == null || sender.isEmpty) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text(AppLocalizations.of(context).noSenderMessage)),
        );
      }
      return;
    }

    if (receiver == null || receiver.isEmpty) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text(AppLocalizations.of(context).noRecipientMessage),
          ),
        );
      }
      return;
    }

    final result = await _webSocketService.sendChatMessage(
      sender: sender,
      receiver: receiver,
      content: text,
      jobId: _activeChat.jobId,
      jobNumber: _activeChat.jobNumber,
    );

    if (result == null) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text(AppLocalizations.of(context).messageSendError),
          ),
        );
      }
      return;
    }

    _syncActiveChatFromService();

    _messageController.clear();

    _scrollToBottom();
  }

  @override
  Widget build(BuildContext context) {
    final isJobChat = _activeChat.type == ChatType.jobSpecific;

    return Scaffold(
      appBar: AppBar(
        title: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              localizedChatTitle(context, _activeChat),
              style: const TextStyle(fontSize: 16),
            ),
            if (isJobChat && _activeChat.jobNumber != null)
              Text(
                'Job-Nr: ${_activeChat.jobNumber}',
                style: TextStyle(
                  fontSize: 12,
                  color: AppColors.textMuted,
                  fontWeight: FontWeight.normal,
                ),
              ),
          ],
        ),
        actions: [
          IconButton(
            icon: Icon(isJobChat ? Icons.work : Icons.support_agent),
            onPressed: () {
              // Show chat info
              _showChatInfo();
            },
            tooltip: AppLocalizations.of(context).chatInfo,
          ),
        ],
      ),
      body: Column(
        children: [
          const OfflineBanner(),
          // Messages list
          Expanded(
            child: Container(
              decoration: const BoxDecoration(color: AppColors.surfaceMuted),
              child: ListView.builder(
                controller: _scrollController,
                padding: const EdgeInsets.fromLTRB(8, 8, 8, 96),
                itemCount: _messages.length,
                itemBuilder: (context, index) {
                  final message = _messages[index];
                  return _buildMessageBubble(message);
                },
              ),
            ),
          ),
          // Message input
          _buildMessageInput(),
        ],
      ),
    );
  }

  Widget _buildMessageBubble(ChatMessage message) {
    final isOwn = message.isOwn;
    final isImage = message.contentType == ChatContentType.image;

    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 2),
      child: Row(
        mainAxisAlignment:
            isOwn ? MainAxisAlignment.end : MainAxisAlignment.start,
        children: [
          if (!isOwn) const SizedBox(width: 8),
          Flexible(
            child: Container(
              constraints: BoxConstraints(
                maxWidth: MediaQuery.of(context).size.width * 0.7,
              ),
              margin: EdgeInsets.only(
                left: isOwn ? 40 : 0,
                right: isOwn ? 0 : 40,
              ),
              padding: EdgeInsets.symmetric(
                horizontal: isImage ? 6 : 12,
                vertical: isImage ? 6 : 8,
              ),
              decoration: BoxDecoration(
                color: isOwn ? AppColors.primarySoft : AppColors.surface,
                borderRadius: BorderRadius.only(
                  topLeft: const Radius.circular(12),
                  topRight: const Radius.circular(12),
                  bottomLeft: Radius.circular(isOwn ? 12 : 4),
                  bottomRight: Radius.circular(isOwn ? 4 : 12),
                ),
                boxShadow: [
                  BoxShadow(
                    color: Colors.black.withValues(alpha: 0.1),
                    blurRadius: 2,
                    offset: const Offset(0, 1),
                  ),
                ],
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  _buildMessageContent(message, isImage: isImage),
                  const SizedBox(height: 4),
                  Row(
                    mainAxisSize: MainAxisSize.min,
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: [
                      Text(
                        _formatMessageTime(message.createdAt),
                        style: const TextStyle(
                          fontSize: 11,
                          color: AppColors.textMuted,
                        ),
                      ),
                      if (isOwn) ...[
                        const SizedBox(width: 4),
                        Icon(
                          message.pendingSync
                              ? Icons.schedule
                              : (message.read ? Icons.done_all : Icons.done),
                          size: 14,
                          color:
                              message.pendingSync
                                  ? AppColors.warning
                                  : (message.read
                                      ? AppColors.primary
                                      : AppColors.textMuted),
                        ),
                      ],
                    ],
                  ),
                ],
              ),
            ),
          ),
          if (isOwn) const SizedBox(width: 8),
        ],
      ),
    );
  }

  Widget _buildMessageContent(ChatMessage message, {required bool isImage}) {
    if (!isImage) {
      return Text(
        message.content,
        style: const TextStyle(fontSize: 15, color: AppColors.textStrong),
      );
    }

    final imageBytes = _imageCache[message.id] ?? _decodeImageBytes(message);

    if (imageBytes == null) {
      return const Text(
        'Bild konnte nicht geladen werden.',
        style: TextStyle(fontSize: 15),
      );
    }

    return GestureDetector(
      onTap: () => _showImagePreview(imageBytes),
      child: ClipRRect(
        borderRadius: BorderRadius.circular(12),
        child: Container(
          color: Colors.black.withValues(alpha: 0.05),
          constraints: const BoxConstraints(maxWidth: 260, minWidth: 140),
          child: AspectRatio(
            aspectRatio: 4 / 3,
            child: Image.memory(imageBytes, fit: BoxFit.cover),
          ),
        ),
      ),
    );
  }

  Uint8List? _decodeImageBytes(ChatMessage message) {
    final rawContent = message.content.trim();
    if (rawContent.isEmpty) {
      return null;
    }

    final base64Payload =
        rawContent.startsWith('data:')
            ? rawContent.substring(rawContent.indexOf(',') + 1)
            : rawContent;

    final normalized = base64Payload.replaceAll(RegExp(r'\s'), '');

    try {
      final bytes = base64Decode(normalized);
      _imageCache[message.id] = bytes;
      return bytes;
    } catch (_) {
      return null;
    }
  }

  Future<void> _showImagePreview(Uint8List imageBytes) async {
    if (!mounted) return;
    await showDialog<void>(
      context: context,
      builder: (context) {
        return Dialog(
          insetPadding: const EdgeInsets.all(16),
          backgroundColor: Colors.black,
          child: InteractiveViewer(
            child: Image.memory(imageBytes, fit: BoxFit.contain),
          ),
        );
      },
    );
  }

  Widget _buildMessageInput() {
    return Container(
      padding: const EdgeInsets.all(8),
      decoration: BoxDecoration(
        color: AppColors.surface,
        border: const Border(top: BorderSide(color: AppColors.border)),
      ),
      child: SafeArea(
        child: Row(
          children: [
            GestureDetector(
              onTap: _handleAttachmentTap,
              child: Container(
                padding: const EdgeInsets.all(8),
                decoration: BoxDecoration(
                  color: AppColors.surfaceMuted,
                  borderRadius: BorderRadius.circular(20),
                ),
                child: const Icon(
                  Icons.attach_file,
                  color: AppColors.text,
                  size: 20,
                ),
              ),
            ),
            const SizedBox(width: 8),
            Expanded(
              child: Container(
                decoration: BoxDecoration(
                  color: AppColors.surfaceMuted,
                  borderRadius: BorderRadius.circular(20),
                ),
                child: TextField(
                  controller: _messageController,
                  decoration: InputDecoration(
                    hintText: AppLocalizations.of(context).typeMessage,
                    contentPadding: EdgeInsets.symmetric(
                      horizontal: 16,
                      vertical: 8,
                    ),
                    border: InputBorder.none,
                  ),
                  maxLines: null,
                  keyboardType: TextInputType.multiline,
                  textInputAction: TextInputAction.send,
                  onSubmitted: (_) => _sendMessage(),
                ),
              ),
            ),
            const SizedBox(width: 8),
            GestureDetector(
              onTap: () {
                _sendMessage();
              },
              child: Container(
                padding: const EdgeInsets.all(8),
                decoration: BoxDecoration(
                  color: AppColors.primary,
                  borderRadius: BorderRadius.circular(20),
                ),
                child: const Icon(Icons.send, color: Colors.white, size: 20),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Future<void> _handleAttachmentTap() async {
    if (!mounted) return;
    final Uint8List? photoBytes = await showDialog<Uint8List>(
      context: context,
      builder: (context) => const ChatPhotoDialog(),
    );

    if (photoBytes == null || photoBytes.isEmpty) {
      return;
    }

    await _sendImageMessage(photoBytes);
  }

  Future<void> _sendImageMessage(Uint8List imageBytes) async {
    final sender = _currentUserId;
    final receiver = _activeChat.receiver;

    if (sender == null || sender.isEmpty) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text(AppLocalizations.of(context).noSenderMessage)),
        );
      }
      return;
    }

    if (receiver == null || receiver.isEmpty) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text(AppLocalizations.of(context).noRecipientMessage),
          ),
        );
      }
      return;
    }

    final prepared = await _prepareImagePayload(imageBytes);
    if (prepared == null) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text(AppLocalizations.of(context).photoProcessError),
          ),
        );
      }
      return;
    }

    final result = await _webSocketService.sendChatMessage(
      sender: sender,
      receiver: receiver,
      content: prepared.base64DataUri,
      contentType: ChatContentType.image,
      jobId: _activeChat.jobId,
      jobNumber: _activeChat.jobNumber,
    );

    if (result == null) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text(AppLocalizations.of(context).imageSendError)),
        );
      }
      return;
    }

    _syncActiveChatFromService();

    if (prepared.bytes.isNotEmpty) {
      _imageCache[result.id] = prepared.bytes;
    }
  }

  Future<_PreparedImage?> _prepareImagePayload(Uint8List originalBytes) async {
    try {
      final decoded = img.decodeImage(originalBytes);
      if (decoded == null) {
        return null;
      }

      final baked = img.bakeOrientation(decoded);
      const maxDimension = 1280;
      img.Image processed = baked;

      if (baked.width > maxDimension || baked.height > maxDimension) {
        final scale =
            baked.width > baked.height
                ? maxDimension / baked.width
                : maxDimension / baked.height;
        final targetWidth = (baked.width * scale).round();
        final targetHeight = (baked.height * scale).round();
        processed = img.copyResize(
          baked,
          width: targetWidth,
          height: targetHeight,
          interpolation: img.Interpolation.average,
        );
      }

      final encodedBytes = Uint8List.fromList(
        img.encodeJpg(processed, quality: 85),
      );
      final base64Payload = base64Encode(encodedBytes);
      final dataUri = 'data:image/jpeg;base64,$base64Payload';

      return _PreparedImage(base64DataUri: dataUri, bytes: encodedBytes);
    } catch (_) {
      return null;
    }
  }

  String _formatMessageTime(DateTime dateTime) {
    final now = DateTime.now();
    final today = DateTime(now.year, now.month, now.day);
    final messageDate = DateTime(dateTime.year, dateTime.month, dateTime.day);

    if (messageDate == today) {
      // Today - show only time
      return '${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')}';
    } else if (messageDate == today.subtract(const Duration(days: 1))) {
      // Yesterday
      return '${AppLocalizations.of(context).yesterday} ${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')}';
    } else {
      // Older - show date and time
      return '${dateTime.day.toString().padLeft(2, '0')}.${dateTime.month.toString().padLeft(2, '0')} ${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')}';
    }
  }

  void _showChatInfo() {
    final isJobChat = _activeChat.type == ChatType.jobSpecific;

    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text(localizedChatTitle(context, _activeChat)),
          content: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                '${AppLocalizations.of(context).status}: ${isJobChat ? AppLocalizations.of(context).chatTypeJob : AppLocalizations.of(context).chatTypeGeneral}',
              ),
              const SizedBox(height: 8),
              if (isJobChat && _activeChat.jobNumber != null) ...[
                Text(
                  '${AppLocalizations.of(context).jobNumber}: ${_activeChat.jobNumber}',
                ),
                const SizedBox(height: 8),
              ],
              Text(
                '${AppLocalizations.of(context).messages}: ${_messages.length}',
              ),
              const SizedBox(height: 8),
              Text(
                '${AppLocalizations.of(context).created}: ${_formatMessageTime(_messages.isNotEmpty ? _messages.first.createdAt : DateTime.now())}',
              ),
            ],
          ),
          actions: [
            TextButton(
              onPressed: () {
                Navigator.of(context).pop();
              },
              child: Text(AppLocalizations.of(context).close),
            ),
          ],
        );
      },
    );
  }
}
