import 'package:flutter/material.dart';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:hive_flutter/hive_flutter.dart';

import 'package:together_mobile/database/box_type.dart';
import 'package:together_mobile/models/websocket_model.dart';
import 'package:together_mobile/utils/app_dir.dart';
import 'package:together_mobile/utils/format_datetime.dart';
import 'components/chat_tile.dart';
import 'package:together_mobile/models/contact_model.dart';
import 'package:together_mobile/models/apply_list_model.dart';
import 'package:together_mobile/request/apply.dart';
import 'package:together_mobile/request/server.dart';
import 'package:together_mobile/request/contact.dart';
import 'package:together_mobile/models/user_model.dart';
import 'package:together_mobile/models/init_get_it.dart';
import 'package:together_mobile/request/user_profile.dart';
import 'package:together_mobile/database/hive_database.dart';

class ChatScreen extends StatefulWidget {
  const ChatScreen({super.key});

  @override
  State<ChatScreen> createState() => _ChatScreenState();
}

class _ChatScreenState extends State<ChatScreen> {
  Future<bool> _initData() async {
    List<int> encryptionKeyUint8List = await getEncryptKey();

    await Hive.initFlutter(await getBoxPath());

    Box<ChatSetting> chatSettingBox =
        await Hive.openBox<ChatSetting>('chat_setting');

    final openedChats =
        chatSettingBox.values.where((element) => element.isOpen);

    for (var chatBox in openedChats) {
      Hive.openBox<MessageT>(
        'message_${chatBox.contactId}',
        encryptionCipher: HiveAesCipher(encryptionKeyUint8List),
        compactionStrategy: (entries, deletedEntries) => entries > 200,
      );
    }
    if (!getIt.get<UserProfile>().isInitialised) {
      getIt.get<WebSocketManager>().connect(getIt.get<UserAccount>().id);

      List<Map<String, dynamic>> res = await Future.wait([
        getMyProfile(getIt.get<UserAccount>().id),
        getApplyList(getIt.get<UserAccount>().id),
        getContact(getIt.get<UserAccount>().id),
      ]);

      await getIt.get<UserProfile>().init(res[0]['data']);

      if (res[1]['code'] == 10600) {
        getIt.get<ApplyList>().init(res[1]['data']);
      }

      if (res[2]['code'] == 10700) {
        getIt.get<Contact>().init(res[2]['data']);
      }

      Map<String, dynamic> contactAcctProfRes = await getContactAccountProfiles(
        getIt.get<Contact>().friends.keys.toList(),
      );

      if (contactAcctProfRes['code'] == 10700) {
        getIt.get<ContactAccountProfile>().init(contactAcctProfRes['data']);
      }
    }

    return Future(() => true);
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: _initData(),
      builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
        if (snapshot.hasData) {
          return Scaffold(
            appBar: AppBar(
              leading: getIt.get<UserProfile>().avatar.isEmpty
                  ? const CircleAvatar(
                      backgroundImage: AssetImage('assets/images/user_2.png'),
                    )
                  : CircleAvatar(
                      backgroundImage: CachedNetworkImageProvider(
                        '$avatarsUrl/${getIt.get<UserProfile>().avatar}',
                      ),
                    ),
              title: Text(getIt.get<UserProfile>().nickname),
              centerTitle: true,
              actions: [
                IconButton(
                  onPressed: () {},
                  splashRadius: 20,
                  icon: const Icon(Icons.search),
                ),
                IconButton(
                  onPressed: () {},
                  splashRadius: 20,
                  icon: const Icon(Icons.add),
                ),
              ],
            ),
            // Use ListView.builder because it renders list element on demand
            body: RefreshIndicator(
              onRefresh: () async {
                return Future.delayed(
                  const Duration(
                    seconds: 2,
                  ),
                );
              },
              child: ValueListenableBuilder(
                valueListenable:
                    Hive.box<ChatSetting>('chat_setting').listenable(),
                builder: (context, Box<ChatSetting> box, _) {
                  final openedChat =
                      box.values.where((element) => element.isOpen).toList();
                  if (openedChat.isEmpty) {
                    return const Center(
                      child: Text(
                        '没有最新消息',
                        style: TextStyle(
                          fontSize: 18,
                          letterSpacing: 5.0,
                        ),
                      ),
                    );
                  } else {
                    return ListView.builder(
                      physics: const BouncingScrollPhysics(
                        parent: AlwaysScrollableScrollPhysics(),
                      ),
                      itemCount: openedChat.length,
                      itemBuilder: (BuildContext context, int index) {
                        String contactId = openedChat[index].contactId;
                        String showedTime = formatTileDateTime(
                          openedChat[index].latestDateTime!,
                        );

                        return ValueListenableBuilder(
                          valueListenable:
                              Hive.box<MessageT>('message_$contactId')
                                  .listenable(),
                          builder: (context, messageTBox, _) {
                            int length = messageTBox.length;
                            if (length > 0) {
                              MessageT messageT =
                                  messageTBox.getAt(length - 1)!;
                              return ChatTile(
                                index: index,
                                contactId: contactId,
                                senderId: messageT.senderId,
                                type: messageT.type,
                                text: messageT.text,
                                attachments: messageT.attachments,
                                dateTime: showedTime,
                                isShowTime: messageT.isShowTime,
                              );
                            } else {
                              return ChatTile(
                                index: index,
                                contactId: contactId,
                                senderId: '',
                                type: '',
                                text: '',
                                attachments: const [],
                                dateTime: showedTime,
                                isShowTime: false,
                              );
                            }
                          },
                        );
                      },
                    );
                  }
                },
              ),
            ),
          );
        } else {
          return const Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                SizedBox(
                  width: 60,
                  height: 60,
                  child: CircularProgressIndicator(),
                ),
                Padding(
                  padding: EdgeInsets.only(top: 20),
                  child: Text('Loading data....'),
                )
              ],
            ),
          );
        }
      },
    );
  }
}