import 'dart:convert';
import 'dart:io';

import 'package:Capsule/utils/storage/session_cookie.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

import '/components/custom_title_bar.dart';
import '/components/flash_message.dart';
import '/components/select_message_ttl.dart';
import '/exceptions/update_data_exception.dart';
import '/models/friends.dart';
import '/utils/encryption/crypto_utils.dart';
import '/utils/storage/write_file.dart';
import '/views/main/conversation/create_add_users.dart';
import '/models/conversation_users.dart';
import '/models/conversations.dart';
import '/models/my_profile.dart';
import '/views/main/conversation/settings_user_list_item.dart';
import '/views/main/conversation/edit_details.dart';
import '/components/custom_circle_avatar.dart';
import '/utils/storage/database.dart';
import '/utils/storage/conversations.dart';

class ConversationSettings extends StatefulWidget {
  final Conversation conversation;
  const ConversationSettings({
    Key? key,
    required this.conversation,
  }) : super(key: key);

  @override
  State<ConversationSettings> createState() => _ConversationSettingsState();
}

class _ConversationSettingsState extends State<ConversationSettings> {
  List<ConversationUser> users = [];
  MyProfile? profile;

  TextEditingController nameController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: CustomTitleBar(
        title: Text(
          widget.conversation.name + ' Settings',
          style: TextStyle(
            fontSize: 16,
            fontWeight: FontWeight.w600,
            color: Theme.of(context).appBarTheme.toolbarTextStyle?.color
          ),
        ),
        showBack: true,
      ),
      body: Padding(
        padding: const EdgeInsets.all(15),
        child: SingleChildScrollView(
          child: Column(
            children: <Widget> [
              const SizedBox(height: 30),
              conversationName(),
              const SizedBox(height: 25),
              widget.conversation.admin ?
              sectionTitle('Settings') :
              const SizedBox.shrink(),
              widget.conversation.admin ?
              settings() :
              const SizedBox.shrink(),
              widget.conversation.admin ?
              const SizedBox(height: 25) :
              const SizedBox.shrink(),
              sectionTitle('Members', showUsersAdd: widget.conversation.admin && !widget.conversation.twoUser),
              usersList(),
              const SizedBox(height: 25),
              myAccess(),
            ],
          ),
        ),
      ),
    );
  }

  Widget conversationName() {
    return Row(
      children: <Widget> [

        CustomCircleAvatar(
          icon: const Icon(Icons.people, size: 40),
          radius: 30,
          image: widget.conversation.icon,
        ),

        const SizedBox(width: 10),

        Text(
          widget.conversation.name,
          style: const TextStyle(
            fontSize: 25,
            fontWeight: FontWeight.w500,
          ),
        ),

        widget.conversation.admin && !widget.conversation.twoUser ? IconButton(
          iconSize: 20,
          icon: const Icon(Icons.edit),
          padding: const EdgeInsets.all(5.0),
          splashRadius: 25,
          onPressed: () {
            Navigator.of(context).push(
              MaterialPageRoute(builder: (context) => ConversationEditDetails(
                // TODO: Move saveCallback to somewhere else
                saveCallback: (String conversationName, File? file) async {

                  bool updatedImage = false;

                  File? writtenFile;
                  if (file != null) {
                    updatedImage = file.hashCode != widget.conversation.icon.hashCode;
                    writtenFile = await writeImage(
                      widget.conversation.id,
                      file.readAsBytesSync(),
                    );
                  }

                  widget.conversation.name = conversationName;
                  widget.conversation.icon = writtenFile;

                  await saveConversation();

                  await updateConversation(widget.conversation, updatedImage: updatedImage)
                      .catchError((error) {
                        String message = error.toString();
                        if (error.runtimeType != UpdateDataException) {
                          message = 'An error occured, please try again later';
                        }

                        showMessage(message, context);
                      });
                  setState(() {});
                  Navigator.pop(context);
                },
                conversation: widget.conversation,
              )),
            ).then(onGoBack);
          },
        ) : const SizedBox.shrink(),
      ],
    );
  }

  Future<void> getUsers() async {
    users = await getConversationUsers(widget.conversation);
    profile = await MyProfile.getProfile();
    setState(() {});
  }

  @override
  void initState() {
    nameController.text = widget.conversation.name;
    super.initState();
    getUsers();
  }

  Widget myAccess() {
    return Align(
      alignment: Alignment.centerLeft,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          TextButton.icon(
            label: const Text(
              'Leave Conversation',
              style: TextStyle(fontSize: 16)
            ),
            icon: const Icon(Icons.exit_to_app),
            style: const ButtonStyle(
              alignment: Alignment.centerLeft,
            ),
            onPressed: () {
              print('Leave Group');
            }
          ),
        ],
      ),
    );
  }

  Widget sectionTitle(String title, { bool showUsersAdd = false}) {
    return Align(
      alignment: Alignment.centerLeft,
      child: Padding(
        padding: const EdgeInsets.only(right: 6),
        child: Row(
          children: [
            Expanded(
              child: Container(
                padding: const EdgeInsets.only(left: 12),
                child: Text(
                  title,
                  style: const TextStyle(fontSize: 20),
                ),
              ),
            ),
            !showUsersAdd ?
            const SizedBox.shrink() :
            IconButton(
              icon: const Icon(Icons.add),
              padding: const EdgeInsets.all(0),
              onPressed: () async {
                List<Friend> friends = await unselectedFriends();
                Navigator.of(context).push(
                  MaterialPageRoute(builder: (context) => ConversationAddFriendsList(
                    friends: friends,
                    saveCallback: (List<Friend> selectedFriends) async {
                      addUsersToConversation(
                        widget.conversation,
                        selectedFriends,
                      );

                      await updateConversation(widget.conversation, includeUsers: true);
                      await getUsers();
                      Navigator.pop(context);
                    },
                  ))
                );
              },
            ),
          ],
        )
      )
    );
  }

  Widget settings() {
    return Align(
      alignment: Alignment.centerLeft,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          const SizedBox(height: 5),
          TextButton.icon(
            label: const Text(
              'Disappearing Messages',
              style: TextStyle(fontSize: 16)
            ),
            icon: const Icon(Icons.timer),
            style: ButtonStyle(
              alignment: Alignment.centerLeft,
              foregroundColor: MaterialStateProperty.resolveWith<Color>(
              (Set<MaterialState> states) {
                  return Theme.of(context).colorScheme.onBackground;
                },
              )
            ),
            onPressed: () {
              Navigator.of(context).push(
                MaterialPageRoute(builder: (context) => SelectMessageTTL(
                  widgetTitle: 'Message Expiry',
                  currentSelected: widget.conversation.messageExpiryDefault,
                  backCallback: (String messageExpiry) async {
                    widget.conversation.messageExpiryDefault = messageExpiry;

                    http.post(
                      await MyProfile.getServerUrl(
                        'api/v1/auth/conversations/${widget.conversation.id}/message_expiry'
                      ),
                      headers: {
                        'cookie': await getSessionCookie(),
                      },
                      body: jsonEncode({
                        'message_expiry': messageExpiry,
                      }),
                    ).then((http.Response response) {
                      if (response.statusCode == 204) {
                        return;
                      }

                      showMessage(
                        'Could not change the default message expiry, please try again later.',
                        context,
                      );
                    });

                    saveConversation();
                  }
                ))
              );
            }
          ),
          TextButton.icon(
            label: const Text(
              'Permissions',
              style: TextStyle(fontSize: 16)
            ),
            icon: const Icon(Icons.lock),
            style: ButtonStyle(
              alignment: Alignment.centerLeft,
foregroundColor: MaterialStateProperty.resolveWith<Color>(
(Set<MaterialState> states) {
return Theme.of(context).colorScheme.onBackground;
},
              )
            ),
            onPressed: () {
              print('Permissions');
            }
          ),
        ],
      ),
    );
  }

  Widget usersList() {
    return ListView.builder(
      itemCount: users.length,
      shrinkWrap: true,
      padding: const EdgeInsets.only(top: 5, bottom: 0),
      physics: const NeverScrollableScrollPhysics(),
      itemBuilder: (context, i) {
        return ConversationSettingsUserListItem(
          user: users[i],
          isAdmin: widget.conversation.admin,
          profile: profile!, // TODO: Fix this
        );
      }
    );
  }

  Future<List<Friend>> unselectedFriends() async {
    final db = await getDatabaseConnection();

    List<String> notInArgs = [];
    for (var user in users) {
    notInArgs.add(user.userId);
  }

    final List<Map<String, dynamic>> maps = await db.query(
      'friends',
      where: 'friend_id not in (${List.filled(notInArgs.length, '?').join(',')})',
      whereArgs: notInArgs,
      orderBy: 'username',
    );

    return List.generate(maps.length, (i) {
      return Friend(
        id: maps[i]['id'],
        userId: maps[i]['user_id'],
        friendId: maps[i]['friend_id'],
        friendSymmetricKey: maps[i]['symmetric_key'],
        publicKey: CryptoUtils.rsaPublicKeyFromPem(maps[i]['asymmetric_public_key']),
        acceptedAt: maps[i]['accepted_at'],
        username: maps[i]['username'],
      );
    });
  }

  onGoBack(dynamic value) async {
    nameController.text = widget.conversation.name;
    getUsers();
    setState(() {});
  }

  saveConversation() async {
    final db = await getDatabaseConnection();
    db.update(
      'conversations',
      widget.conversation.toMap(),
      where: 'id = ?',
      whereArgs: [widget.conversation.id],
    );
  }
}

