import 'dart:convert';
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

import '/components/flash_message.dart';
import '/components/custom_circle_avatar.dart';
import '/models/friends.dart';
import '/models/my_profile.dart';
import '/utils/storage/session_cookie.dart';
import '/utils/storage/database.dart';
import '/utils/encryption/aes_helper.dart';
import '/utils/encryption/crypto_utils.dart';
import '/utils/strings.dart';


class FriendRequestListItem extends StatefulWidget{
  final Friend friend;
  final Function callback;

  const FriendRequestListItem({
    Key? key,
    required this.friend,
    required this.callback,
  }) : super(key: key);

  @override
  _FriendRequestListItemState createState() => _FriendRequestListItemState();
}

class _FriendRequestListItemState extends State<FriendRequestListItem> {

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      behavior: HitTestBehavior.opaque,
      onTap: () async {
      },
      child: Container(
        padding: const EdgeInsets.only(left: 16,right: 10,top: 0,bottom: 20),
        child: Row(
          children: <Widget>[
            Expanded(
              child: Row(
                children: <Widget>[
                  CustomCircleAvatar(
                    initials: widget.friend.username[0].toUpperCase(),
                  ),
                  const SizedBox(width: 16),
                  Expanded(
                    child: Align(
                      alignment: Alignment.centerLeft,
                      child: Container(
                        color: Colors.transparent,
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: <Widget>[
                            Text(widget.friend.username, style: const TextStyle(fontSize: 16)),
                          ],
                        ),
                      ),
                    ),
                  ),
                  SizedBox(
                    height: 30,
                    width: 30,
                    child: IconButton(
                      onPressed: () { acceptFriendRequest(context); },
                      icon: const Icon(Icons.check),
                      padding: const EdgeInsets.all(0),
                      splashRadius: 20,
                    ),
                  ),
                  const SizedBox(width: 6),
                  SizedBox(
                    height: 30,
                    width: 30,
                    child: IconButton(
                      onPressed: rejectFriendRequest,
                      icon: const Icon(Icons.cancel),
                      padding: const EdgeInsets.all(0),
                      splashRadius: 20,
                    ),
                  ),
                ],
             ),
           ),
         ],
        ),
      ),
    );
  }

  Future<void> acceptFriendRequest(BuildContext context) async {
    MyProfile profile = await MyProfile.getProfile();

    String publicKeyString = CryptoUtils.encodeRSAPublicKeyToPem(profile.publicKey!);

    final symmetricKey = AesHelper.deriveKey(generateRandomString(32));

    String payloadJson = jsonEncode({
      'user_id': widget.friend.friendId,
      'friend_id': base64.encode(CryptoUtils.rsaEncrypt(
          Uint8List.fromList(profile.id.codeUnits),
          widget.friend.publicKey,
      )),
      'friend_username': base64.encode(CryptoUtils.rsaEncrypt(
          Uint8List.fromList(profile.username.codeUnits),
          widget.friend.publicKey,
      )),
      'symmetric_key': base64.encode(CryptoUtils.rsaEncrypt(
          Uint8List.fromList(symmetricKey),
          widget.friend.publicKey,
      )),
      'asymmetric_public_key': AesHelper.aesEncrypt(
          symmetricKey,
          Uint8List.fromList(publicKeyString.codeUnits),
      ),
    });

    var resp = await http.post(
        await MyProfile.getServerUrl('api/v1/auth/friend_request/${widget.friend.id}'),
        headers: {
          'cookie': await getSessionCookie(),
        },
        body: payloadJson,
    );

    if (resp.statusCode != 204) {
      showMessage(
        'Failed to accept friend request, please try again later',
        context
      );
      return;
    }

    final db = await getDatabaseConnection();

    widget.friend.acceptedAt = DateTime.now();

    await db.update(
      'friends',
      widget.friend.toMap(),
      where: 'id = ?',
      whereArgs: [widget.friend.id],
    );

    widget.callback();
  }

  Future<void> rejectFriendRequest() async {
    var resp = await http.delete(
        await MyProfile.getServerUrl('api/v1/auth/friend_request/${widget.friend.id}'),
        headers: {
          'cookie': await getSessionCookie(),
        },
    );

    if (resp.statusCode != 204) {
      showMessage(
        'Failed to decline friend request, please try again later',
        context
      );
      return;
    }

    final db = await getDatabaseConnection();

    await db.delete(
      'friends',
      where: 'id = ?',
      whereArgs: [widget.friend.id],
    );

    widget.callback();
  }
}
