// Version: 1.1.0 | Created: 2026-04-01
// Message input bar — text, send, attach file, reply quote.
// File picker enabled in Phase 2 via file_picker ^8.0.0.

import 'dart:typed_data';

import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:matrix/matrix.dart' show MatrixFile;

/// Describes a pending reply — shown as a quote above the input field.
class ReplyTo {
  const ReplyTo({
    required this.eventId,
    required this.senderDisplayName,
    required this.body,
  });

  final String eventId;
  final String senderDisplayName;
  final String body;
}

class MessageInput extends StatefulWidget {
  const MessageInput({
    super.key,
    required this.onSend,
    required this.isSending,
    this.replyTo,
    this.onCancelReply,
    this.onAttach,
  });

  /// Called with text content when the user sends a plain text message.
  final Future<void> Function(String text) onSend;

  /// Called with a [MatrixFile] when the user picks an attachment.
  final Future<void> Function(MatrixFile file)? onAttach;

  /// Whether a send/upload operation is in progress.
  final bool isSending;

  /// If non-null, a reply quote is shown above the input.
  final ReplyTo? replyTo;

  /// Called when the user cancels the pending reply.
  final VoidCallback? onCancelReply;

  @override
  State<MessageInput> createState() => _MessageInputState();
}

class _MessageInputState extends State<MessageInput> {
  final _controller = TextEditingController();
  final _focusNode = FocusNode();
  bool _hasText = false;
  bool _isPickingFile = false;

  @override
  void initState() {
    super.initState();
    _controller.addListener(() {
      final hasText = _controller.text.trim().isNotEmpty;
      if (hasText != _hasText) setState(() => _hasText = hasText);
    });
  }

  @override
  void dispose() {
    _controller.dispose();
    _focusNode.dispose();
    super.dispose();
  }

  Future<void> _submit() async {
    final text = _controller.text.trim();
    if (text.isEmpty) return;
    _controller.clear();
    await widget.onSend(text);
    // Return focus to the input so the user can keep typing.
    _focusNode.requestFocus();
  }

  Future<void> _pickFile() async {
    if (_isPickingFile) return;
    setState(() => _isPickingFile = true);

    try {
      final result = await FilePicker.platform.pickFiles(
        withData: true, // required on web — reads bytes immediately
      );

      if (result == null || result.files.isEmpty) return;

      final picked = result.files.first;
      final Uint8List? bytes = picked.bytes;
      if (bytes == null || bytes.isEmpty) {
        if (mounted) {
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text('Could not read file data.')),
          );
        }
        return;
      }

      final matrixFile = MatrixFile(
        bytes: bytes,
        name: picked.name,
        mimeType: picked.extension != null
            ? _mimeFromExtension(picked.extension!)
            : null,
      );

      await widget.onAttach?.call(matrixFile);
    } finally {
      if (mounted) setState(() => _isPickingFile = false);
    }
  }

  String? _mimeFromExtension(String ext) {
    return switch (ext.toLowerCase()) {
      'jpg' || 'jpeg' => 'image/jpeg',
      'png' => 'image/png',
      'gif' => 'image/gif',
      'webp' => 'image/webp',
      'mp4' => 'video/mp4',
      'mov' => 'video/quicktime',
      'mp3' => 'audio/mpeg',
      'ogg' => 'audio/ogg',
      'pdf' => 'application/pdf',
      _ => null,
    };
  }

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

    return Container(
      decoration: BoxDecoration(
        color: theme.colorScheme.surface,
        border: Border(
          top: BorderSide(color: theme.colorScheme.outline.withAlpha(51)),
        ),
      ),
      child: SafeArea(
        top: false,
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            // Reply quote strip
            if (widget.replyTo != null)
              _ReplyQuote(
                replyTo: widget.replyTo!,
                onCancel: widget.onCancelReply ?? () {},
              ),

            // Input row
            Padding(
              padding: const EdgeInsets.fromLTRB(8, 8, 8, 12),
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.end,
                children: [
                  // Attach button
                  if (widget.onAttach != null)
                    IconButton(
                      icon: _isPickingFile
                          ? const SizedBox(
                              width: 20,
                              height: 20,
                              child: CircularProgressIndicator(strokeWidth: 2),
                            )
                          : const Icon(Icons.add),
                      tooltip: 'Attach file',
                      onPressed: (_isPickingFile || widget.isSending)
                          ? null
                          : _pickFile,
                      color: theme.colorScheme.onSurface.withAlpha(153),
                    )
                  else
                    const SizedBox(width: 8),

                  // Text field
                  Expanded(
                    child: TextField(
                      controller: _controller,
                      focusNode: _focusNode,
                      autofocus: true,
                      decoration: const InputDecoration(
                        hintText: 'Message',
                        contentPadding: EdgeInsets.symmetric(
                          horizontal: 16,
                          vertical: 10,
                        ),
                      ),
                      textInputAction: TextInputAction.send,
                      onSubmitted: (_) => _submit(),
                      maxLines: null,
                      keyboardType: TextInputType.multiline,
                    ),
                  ),
                  const SizedBox(width: 8),

                  // Send button
                  AnimatedSwitcher(
                    duration: const Duration(milliseconds: 150),
                    child: widget.isSending
                        ? const SizedBox(
                            width: 40,
                            height: 40,
                            child: Center(
                              child: SizedBox(
                                width: 20,
                                height: 20,
                                child: CircularProgressIndicator(
                                  strokeWidth: 2.5,
                                ),
                              ),
                            ),
                          )
                        : IconButton(
                            icon: const Icon(Icons.send_rounded),
                            onPressed: _hasText ? _submit : null,
                            color: _hasText
                                ? theme.colorScheme.primary
                                : theme.colorScheme.onSurface.withAlpha(77),
                            tooltip: 'Send message',
                          ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

// ---------------------------------------------------------------------------
// Reply quote strip
// ---------------------------------------------------------------------------

class _ReplyQuote extends StatelessWidget {
  const _ReplyQuote({required this.replyTo, required this.onCancel});

  final ReplyTo replyTo;
  final VoidCallback onCancel;

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

    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
      decoration: BoxDecoration(
        border: Border(
          top: BorderSide(color: theme.colorScheme.outline.withAlpha(51)),
          left: BorderSide(color: theme.colorScheme.primary, width: 3),
        ),
      ),
      child: Row(
        children: [
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisSize: MainAxisSize.min,
              children: [
                Text(
                  replyTo.senderDisplayName,
                  style: theme.textTheme.labelSmall?.copyWith(
                    color: theme.colorScheme.primary,
                    fontWeight: FontWeight.w600,
                  ),
                ),
                const SizedBox(height: 2),
                Text(
                  replyTo.body,
                  style: theme.textTheme.bodySmall?.copyWith(
                    color: theme.colorScheme.onSurface.withAlpha(153),
                  ),
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                ),
              ],
            ),
          ),
          IconButton(
            icon: const Icon(Icons.close, size: 18),
            onPressed: onCancel,
            tooltip: 'Cancel reply',
            color: theme.colorScheme.onSurface.withAlpha(153),
          ),
        ],
      ),
    );
  }
}
