// Version: 1.3.0 | Created: 2026-04-01 | Updated: 2026-04-27
// Message bubble widget. Handles text, images, files, redacted, replies.

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

import '../../../shared/widgets/matrix_avatar.dart';
import '../domain/message_model.dart';

class MessageBubble extends StatelessWidget {
  const MessageBubble({super.key, required this.message});

  final MessageModel message;

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

    return Padding(
      padding: EdgeInsets.only(
        top: 2,
        bottom: 2,
        left: isMine ? 48 : 8,
        right: isMine ? 8 : 48,
      ),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.end,
        mainAxisAlignment: isMine
            ? MainAxisAlignment.end
            : MainAxisAlignment.start,
        children: [
          if (!isMine) ...[
            MatrixAvatar(
              name: message.senderDisplayName,
              avatarUrl: message.senderAvatarUrl,
              radius: 16,
            ),
            const SizedBox(width: 8),
          ],
          Flexible(
            child: Column(
              crossAxisAlignment: isMine
                  ? CrossAxisAlignment.end
                  : CrossAxisAlignment.start,
              children: [
                if (!isMine)
                  Padding(
                    padding: const EdgeInsets.only(left: 4, bottom: 2),
                    child: Text(
                      message.senderDisplayName,
                      style: theme.textTheme.labelSmall?.copyWith(
                        color: theme.colorScheme.primary,
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                  ),
                _BubbleContent(message: message, isMine: isMine),
                if (message.reactions.isNotEmpty)
                  _ReactionsRow(reactions: message.reactions),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class _BubbleContent extends StatelessWidget {
  const _BubbleContent({required this.message, required this.isMine});

  final MessageModel message;
  final bool isMine;

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

    final bgColour = isMine
        ? theme.colorScheme.primary
        : theme.colorScheme.surfaceContainerHighest;
    final textColour = isMine ? Colors.white : theme.colorScheme.onSurface;

    return Container(
      constraints: const BoxConstraints(maxWidth: 320),
      decoration: BoxDecoration(
        color: bgColour,
        borderRadius: BorderRadius.only(
          topLeft: const Radius.circular(16),
          topRight: const Radius.circular(16),
          bottomLeft: Radius.circular(isMine ? 16 : 4),
          bottomRight: Radius.circular(isMine ? 4 : 16),
        ),
      ),
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
            _MessageContentBody(message: message, textColour: textColour),
            const SizedBox(height: 2),
            _Timestamp(
              timestamp: message.timestamp,
              isEdited: message.isEdited,
              textColour: textColour.withAlpha(153),
            ),
          ],
        ),
      ),
    );
  }
}

class _MessageContentBody extends StatelessWidget {
  const _MessageContentBody({required this.message, required this.textColour});

  final MessageModel message;
  final Color textColour;

  @override
  Widget build(BuildContext context) {
    return switch (message.type) {
      MessageType.text => Text(
        message.body ?? '',
        style: TextStyle(color: textColour),
      ),
      MessageType.image => _ImageContent(message: message),
      MessageType.file => _FileContent(
        message: message,
        textColour: textColour,
      ),
      MessageType.redacted => Text(
        'This message was deleted.',
        style: TextStyle(
          color: textColour.withAlpha(153),
          fontStyle: FontStyle.italic,
        ),
      ),
      MessageType.encrypted => Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(Icons.lock_outline, size: 14, color: textColour.withAlpha(153)),
          const SizedBox(width: 6),
          Flexible(
            child: Text(
              'Encrypted — use Element to read',
              style: TextStyle(
                color: textColour.withAlpha(153),
                fontStyle: FontStyle.italic,
              ),
            ),
          ),
        ],
      ),
      _ => Text(
        message.body ?? 'Unsupported message type',
        style: TextStyle(
          color: textColour.withAlpha(153),
          fontStyle: FontStyle.italic,
        ),
      ),
    };
  }
}

class _ImageContent extends StatelessWidget {
  const _ImageContent({required this.message});

  final MessageModel message;

  @override
  Widget build(BuildContext context) {
    final url = message.mediaUrl;
    if (url == null) return const Icon(Icons.image_not_supported);

    return GestureDetector(
      onTap: () => _openFullscreen(context, url, message.body),
      child: ClipRRect(
        borderRadius: BorderRadius.circular(8),
        child: CachedNetworkImage(
          imageUrl: url,
          width: 240,
          fit: BoxFit.cover,
          placeholder: (_, __) => const SizedBox(
            height: 160,
            child: Center(child: CircularProgressIndicator()),
          ),
          errorWidget: (_, __, ___) => const SizedBox(
            height: 80,
            child: Center(child: Icon(Icons.broken_image)),
          ),
        ),
      ),
    );
  }

  void _openFullscreen(BuildContext context, String url, String? caption) {
    Navigator.of(context).push(
      MaterialPageRoute<void>(
        fullscreenDialog: true,
        builder: (_) => _ImageViewer(url: url, caption: caption),
      ),
    );
  }
}

class _ImageViewer extends StatelessWidget {
  const _ImageViewer({required this.url, this.caption});

  final String url;
  final String? caption;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      appBar: AppBar(
        backgroundColor: Colors.black,
        foregroundColor: Colors.white,
        title: caption != null
            ? Text(
                caption!,
                style: const TextStyle(fontSize: 14),
                overflow: TextOverflow.ellipsis,
              )
            : null,
      ),
      body: Center(
        child: InteractiveViewer(
          minScale: 0.5,
          maxScale: 4,
          child: CachedNetworkImage(
            imageUrl: url,
            fit: BoxFit.contain,
            placeholder: (_, __) => const CircularProgressIndicator(
              color: Colors.white,
            ),
            errorWidget: (_, __, ___) => const Icon(
              Icons.broken_image,
              color: Colors.white,
              size: 64,
            ),
          ),
        ),
      ),
    );
  }
}

class _FileContent extends StatelessWidget {
  const _FileContent({required this.message, required this.textColour});

  final MessageModel message;
  final Color textColour;

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        Icon(Icons.attach_file, color: textColour, size: 18),
        const SizedBox(width: 6),
        Flexible(
          child: Text(
            message.body ?? 'File',
            style: TextStyle(color: textColour),
            overflow: TextOverflow.ellipsis,
          ),
        ),
      ],
    );
  }
}

class _Timestamp extends StatelessWidget {
  const _Timestamp({
    required this.timestamp,
    required this.isEdited,
    required this.textColour,
  });

  static final DateFormat _timeFormat = DateFormat('HH:mm');

  final DateTime timestamp;
  final bool isEdited;
  final Color textColour;

  @override
  Widget build(BuildContext context) {
    final formatted = _timeFormat.format(timestamp.toLocal());
    final label = isEdited ? '$formatted  (edited)' : formatted;

    return Text(label, style: TextStyle(fontSize: 10, color: textColour));
  }
}

class _ReactionsRow extends StatelessWidget {
  const _ReactionsRow({required this.reactions});

  final Map<String, List<String>> reactions;

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

    return Padding(
      padding: const EdgeInsets.only(top: 4),
      child: Wrap(
        spacing: 4,
        children: reactions.entries.map((entry) {
          return Container(
            padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
            decoration: BoxDecoration(
              color: theme.colorScheme.surfaceContainerHighest,
              borderRadius: BorderRadius.circular(12),
              border: Border.all(
                color: theme.colorScheme.outline.withAlpha(51),
              ),
            ),
            child: Text(
              '${entry.key} ${entry.value.length}',
              style: const TextStyle(fontSize: 12),
            ),
          );
        }).toList(),
      ),
    );
  }
}
