// Version: 1.2.0 | Created: 2026-04-01 | Updated: 2026-04-02
// User search dialog — search Matrix user directory and start a DM.
// Triggered from the rooms screen "New message" button.

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:matrix/matrix_api_lite.dart' show Profile;
import 'package:riverpod_annotation/riverpod_annotation.dart';

import '../../../core/network/matrix_client.dart';
import '../../../shared/utils/mxc_url.dart';
import '../../../shared/widgets/matrix_avatar.dart';

part 'user_search_dialog.g.dart';

// ---------------------------------------------------------------------------
// Provider
// ---------------------------------------------------------------------------

@riverpod
Future<List<Profile>> searchUsers(Ref ref, String term) async {
  if (term.trim().length < 2) return [];
  final client = ref.watch(matrixClientProvider);
  final result = await client.searchUserDirectory(term.trim(), limit: 20);
  return result.results;
}

// ---------------------------------------------------------------------------
// Dialog
// ---------------------------------------------------------------------------

/// Show user search as a modal dialog. On user selected, navigates to DM room.
Future<void> showUserSearchDialog(BuildContext context) async {
  return showDialog(
    context: context,
    builder: (_) => const _UserSearchDialog(),
  );
}

class _UserSearchDialog extends ConsumerStatefulWidget {
  const _UserSearchDialog();

  @override
  ConsumerState<_UserSearchDialog> createState() => _UserSearchDialogState();
}

class _UserSearchDialogState extends ConsumerState<_UserSearchDialog> {
  final _controller = TextEditingController();
  String _searchTerm = '';
  bool _isStartingDm = false;
  Timer? _debounce;

  @override
  void dispose() {
    _debounce?.cancel();
    _controller.dispose();
    super.dispose();
  }

  void _onSearchChanged(String val) {
    _debounce?.cancel();
    _debounce = Timer(const Duration(milliseconds: 400), () {
      if (mounted) setState(() => _searchTerm = val);
    });
  }

  Future<void> _startDm(String userId) async {
    if (_isStartingDm) return;
    setState(() => _isStartingDm = true);

    try {
      final client = ref.read(matrixClientProvider);
      final roomId = await client.startDirectChat(userId);
      if (!mounted) return;
      Navigator.of(context).pop(); // close the dialog
      context.push('/rooms/${Uri.encodeComponent(roomId)}');
    } on Exception catch (e) {
      if (!mounted) return;
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Could not start conversation: $e')),
      );
    } finally {
      if (mounted) setState(() => _isStartingDm = false);
    }
  }

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

    return Dialog(
      insetPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 32),
      child: ConstrainedBox(
        constraints: const BoxConstraints(maxWidth: 480, maxHeight: 520),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            // Header
            Padding(
              padding: const EdgeInsets.fromLTRB(16, 16, 4, 0),
              child: Row(
                children: [
                  Text(
                    'New message',
                    style: theme.textTheme.titleMedium?.copyWith(
                      fontWeight: FontWeight.w600,
                    ),
                  ),
                  const Spacer(),
                  IconButton(
                    icon: const Icon(Icons.close),
                    onPressed: () => Navigator.of(context).pop(),
                  ),
                ],
              ),
            ),

            // Search field
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
              child: TextField(
                controller: _controller,
                autofocus: true,
                decoration: const InputDecoration(
                  hintText: 'Search by name or user ID...',
                  prefixIcon: Icon(Icons.search),
                ),
                onChanged: _onSearchChanged,
              ),
            ),

            // Results
            Flexible(
              child: _searchTerm.trim().length < 2
                  ? Padding(
                      padding: const EdgeInsets.all(24),
                      child: Text(
                        'Type a name or @user:server to search.',
                        style: theme.textTheme.bodySmall?.copyWith(
                          color: theme.colorScheme.onSurface.withAlpha(102),
                        ),
                        textAlign: TextAlign.center,
                      ),
                    )
                  : _SearchResults(
                      term: _searchTerm,
                      isLoading: _isStartingDm,
                      onSelect: _startDm,
                    ),
            ),
          ],
        ),
      ),
    );
  }
}

class _SearchResults extends ConsumerWidget {
  const _SearchResults({
    required this.term,
    required this.isLoading,
    required this.onSelect,
  });

  final String term;
  final bool isLoading;
  final Future<void> Function(String userId) onSelect;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final resultsAsync = ref.watch(searchUsersProvider(term));
    final theme = Theme.of(context);
    final client = ref.watch(matrixClientProvider);

    return resultsAsync.when(
      loading: () => const Center(child: CircularProgressIndicator()),
      error: (err, _) => Padding(
        padding: const EdgeInsets.all(16),
        child: Text('Search failed: $err'),
      ),
      data: (profiles) {
        if (profiles.isEmpty) {
          return Padding(
            padding: const EdgeInsets.all(24),
            child: Text(
              'No users found.',
              style: theme.textTheme.bodySmall?.copyWith(
                color: theme.colorScheme.onSurface.withAlpha(102),
              ),
              textAlign: TextAlign.center,
            ),
          );
        }
        return ListView.builder(
          shrinkWrap: true,
          itemCount: profiles.length,
          itemBuilder: (context, index) {
            final profile = profiles[index];
            final displayName = profile.displayName ?? profile.userId;

            return ListTile(
              leading: MatrixAvatar(
                name: displayName,
                avatarUrl: resolveMxcUrl(client, profile.avatarUrl),
                radius: 20,
              ),
              title: Text(displayName),
              subtitle: Text(
                profile.userId,
                style: theme.textTheme.bodySmall?.copyWith(
                  color: theme.colorScheme.onSurface.withAlpha(153),
                ),
              ),
              enabled: !isLoading,
              onTap: () => onSelect(profile.userId),
            );
          },
        );
      },
    );
  }
}
