// ignore_for_file: parameter_assignments

import 'dart:async';
import 'dart:collection';

import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:twonly/locator.dart';
import 'package:twonly/src/database/daos/contacts.dao.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/visual/components/avatar_icon.comp.dart';
import 'package:twonly/src/visual/components/contact_labels.comp.dart';
import 'package:twonly/src/visual/components/flame_counter.comp.dart';
import 'package:twonly/src/visual/components/snackbar.dart';
import 'package:twonly/src/visual/components/verification_badge.comp.dart';
import 'package:twonly/src/visual/context_menu/user.context_menu.dart';
import 'package:twonly/src/visual/decorations/input_text.decoration.dart';
import 'package:twonly/src/visual/elements/contact_chip.element.dart';
import 'package:twonly/src/visual/elements/my_button.element.dart';
import 'package:twonly/src/visual/views/groups/group_create_select_group_name.view.dart';

class GroupCreateSelectMembersView extends StatefulWidget {
  const GroupCreateSelectMembersView({this.groupId, super.key});
  final String? groupId;
  @override
  State<GroupCreateSelectMembersView> createState() => _StartNewChatView();
}

class _StartNewChatView extends State<GroupCreateSelectMembersView> {
  List<Contact> contacts = [];
  List<Contact> allContacts = [];
  final TextEditingController searchUserName = TextEditingController();
  late StreamSubscription<List<Contact>> contactSub;

  final HashSet<int> selectedUsers = HashSet();
  final HashSet<int> alreadyInGroup = HashSet();

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

    final stream = twonlyDB.contactsDao.watchAllAcceptedContacts();

    contactSub = stream.listen((update) async {
      update.sort(
        (a, b) => getContactDisplayName(a).compareTo(getContactDisplayName(b)),
      );
      setState(() {
        allContacts = update;
      });
      await filterUsers();
    });
    initAsync();
  }

  Future<void> initAsync() async {
    if (widget.groupId != null) {
      final members = await twonlyDB.groupsDao.getGroupContact(widget.groupId!);
      for (final member in members) {
        alreadyInGroup.add(member.userId);
      }
      if (mounted) setState(() {});
    }
  }

  @override
  void dispose() {
    unawaited(contactSub.cancel());
    super.dispose();
  }

  Future<void> filterUsers() async {
    if (searchUserName.value.text.isEmpty) {
      setState(() {
        contacts = allContacts;
      });
      return;
    }
    final usersFiltered = allContacts
        .where(
          (user) => getContactDisplayName(
            user,
          ).toLowerCase().contains(searchUserName.value.text.toLowerCase()),
        )
        .toList();
    setState(() {
      contacts = usersFiltered;
    });
  }

  void toggleSelectedUser(int userId) {
    if (alreadyInGroup.contains(userId)) return;
    if (!selectedUsers.contains(userId)) {
      if (selectedUsers.length + alreadyInGroup.length > 256) {
        showSnackbar(context, context.lang.groupSizeLimitError(256));
        return;
      }
      selectedUsers.add(userId);
    } else {
      selectedUsers.remove(userId);
    }
    setState(() {});
  }

  Future<void> submitChanges() async {
    if (widget.groupId != null) {
      Navigator.pop(context, selectedUsers.toList());
      return;
    }

    await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => GroupCreateSelectGroupNameView(
          selectedUsers: allContacts
              .where((t) => selectedUsers.contains(t.userId))
              .toList(),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => FocusScope.of(context).unfocus(),
      child: Scaffold(
        appBar: AppBar(
          title: Text(
            widget.groupId == null
                ? context.lang.selectMembers
                : context.lang.addMember,
          ),
        ),
        floatingActionButtonAnimator: FloatingActionButtonAnimator.noAnimation,
        floatingActionButton: MyButton(
          variant: MyButtonVariant.primaryMiddle,
          onPressed: selectedUsers.isEmpty ? null : submitChanges,
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              const FaIcon(FontAwesomeIcons.penToSquare, size: 16),
              const SizedBox(width: 8),
              Text(
                widget.groupId == null
                    ? context.lang.next
                    : context.lang.updateGroup,
              ),
            ],
          ),
        ),
        body: SafeArea(
          child: Padding(
            padding: const EdgeInsets.only(
              bottom: 40,
              left: 10,
              top: 20,
              right: 10,
            ),
            child: Column(
              children: [
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 10),
                  child: TextField(
                    onChanged: (_) async {
                      await filterUsers();
                    },
                    controller: searchUserName,
                    decoration: getInputDecoration(
                      context,
                      context.lang.shareImageSearchAllContacts,
                    ),
                  ),
                ),
                const SizedBox(height: 10),
                Expanded(
                  child: ListView.builder(
                    restorationId: 'new_message_users_list',
                    itemCount:
                        contacts.length + (selectedUsers.isEmpty ? 0 : 2),
                    itemBuilder: (context, i) {
                      if (selectedUsers.isNotEmpty) {
                        final selected = selectedUsers.toList();
                        if (i == 0) {
                          return Container(
                            padding: const EdgeInsets.symmetric(horizontal: 18),
                            constraints: const BoxConstraints(
                              maxHeight: 150,
                            ),
                            child: SingleChildScrollView(
                              child: LayoutBuilder(
                                builder: (context, constraints) {
                                  // Wrap will use the available width from constraints.maxWidth
                                  return Wrap(
                                    spacing: 8,
                                    children: selected.map((w) {
                                      final contact = allContacts.firstWhere(
                                        (t) => t.userId == w,
                                      );
                                      return ContactChip(
                                        key: ValueKey(contact.userId),
                                        contact: contact,
                                        onTap: toggleSelectedUser,
                                      );
                                    }).toList(),
                                  );
                                },
                              ),
                            ),
                          );
                        }
                        if (i == 1) {
                          return const Divider();
                        }
                        i -= 2;
                      }
                      final user = contacts[i];
                      return UserContextMenu(
                        key: ValueKey(user.userId),
                        contact: user,
                        child: ContactLabelsSubtitleBuilder(
                          contactId: user.userId,
                          additionalSubtitle: alreadyInGroup.contains(user.userId)
                              ? Text(context.lang.alreadyInGroup)
                              : null,
                          builder: (context, subtitleWidget) {
                            return ListTile(
                              title: Row(
                                children: [
                                  Text(getContactDisplayName(user)),
                                  Padding(
                                    padding: const EdgeInsets.only(
                                      right: 8,
                                      left: 1,
                                    ),
                                    child: VerificationBadgeComp(
                                      contact: user,
                                    ),
                                  ),
                                  FlameCounterWidget(
                                    contactId: user.userId,
                                    prefix: true,
                                  ),
                                ],
                              ),
                              subtitle: subtitleWidget,
                              leading: AvatarIcon(
                                contactId: user.userId,
                                fontSize: 13,
                              ),
                              trailing: Checkbox.adaptive(
                                value:
                                    selectedUsers.contains(user.userId) |
                                    alreadyInGroup.contains(user.userId),
                                side: WidgetStateBorderSide.resolveWith(
                                  (states) {
                                    if (states.contains(WidgetState.selected)) {
                                      return const BorderSide(width: 0);
                                    }
                                    return BorderSide(
                                      color: Theme.of(context).colorScheme.outline,
                                    );
                                  },
                                ),
                                onChanged: (value) {
                                  toggleSelectedUser(user.userId);
                                },
                              ),
                              onTap: () {
                                toggleSelectedUser(user.userId);
                              },
                            );
                          },
                        ),
                      );
                    },
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
