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

import 'package:Capsule/components/file_picker.dart';
import 'package:Capsule/components/flash_message.dart';
import 'package:Capsule/utils/encryption/aes_helper.dart';
import 'package:Capsule/utils/storage/session_cookie.dart';
import 'package:Capsule/utils/storage/write_file.dart';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:image_picker/image_picker.dart';
import 'package:mime/mime.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sliding_up_panel/sliding_up_panel.dart';
import 'package:http/http.dart' as http;

import '/components/select_message_ttl.dart';
import '/components/custom_circle_avatar.dart';
import '/components/custom_title_bar.dart';
import '/models/my_profile.dart';
import '/utils/encryption/crypto_utils.dart';
import '/utils/storage/database.dart';
import '/views/main/profile/change_password.dart';
import '/views/main/profile/change_server_url.dart';

class Profile extends StatefulWidget {
  final MyProfile profile;
  const Profile({
    Key? key,
    required this.profile,
  }) : super(key: key);

  @override
  State<Profile> createState() => _ProfileState();
}

class _ProfileState extends State<Profile> {
  final PanelController _panelController = PanelController();

  bool showFileSelector = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: const CustomTitleBar(
        title: Text(
          'Profile',
          style: TextStyle(
            fontSize: 32,
            fontWeight: FontWeight.bold
          )
        ),
        showBack: false,
        backgroundColor: Colors.transparent,
      ),
      body: SlidingUpPanel(
        controller: _panelController,
        slideDirection: SlideDirection.DOWN,
        defaultPanelState: PanelState.CLOSED,
        color: Theme.of(context).scaffoldBackgroundColor,
        backdropTapClosesPanel: true,
        backdropEnabled: true,
        backdropOpacity: 0.2,
        minHeight: 0,
        panel: Center(
              child: _profileQrCode(),
        ),
        body: Padding(
          padding: const EdgeInsets.only(top: 16,left: 16,right: 16),
          child: Column(
            children: <Widget>[
              usernameHeading(),
              AnimatedSwitcher(
                duration: const Duration(milliseconds: 250),
                transitionBuilder: (Widget child, Animation<double> animation) {
                  return SizeTransition(sizeFactor: animation, child: child);
                },
                child: fileSelector(),
              ),
              SizedBox(height: showFileSelector ? 10 : 30),
              settings(),
              const SizedBox(height: 30),
              logout(),
            ],
          )
        ),
      ),
    );
  }

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

        CustomCircleAvatar(
          image: widget.profile.image,
          icon: const Icon(Icons.person, size: 40),
          radius: 30,
          editImageCallback: () {
            setState(() {
              showFileSelector = true;
            });
          },
        ),

        const SizedBox(width: 20),

        Expanded(
          flex: 1,
          child: Text(
            widget.profile.username,
            style: const TextStyle(
              fontSize: 25,
              fontWeight: FontWeight.w500,
            ),
          ),
        ),

        IconButton(
          onPressed: () => _panelController.open(),
          icon: const Icon(Icons.qr_code_2),
        ),
      ],
    );
  }

  Widget fileSelector() {
    if (!showFileSelector) {
      return const SizedBox.shrink();
    }

    return  Padding(
      key: const Key('fileSelector'),
      padding: const EdgeInsets.only(top: 10),
      child: FilePicker(
        cameraHandle: _setProfileImage,
        galleryHandleSingle: _setProfileImage,
      )
    );
  }

  Future<void> _setProfileImage(XFile image) async {
    widget.profile.image = await writeImage(
      widget.profile.id,
      File(image.path).readAsBytesSync(),
    );

    setState(() {
      showFileSelector = false;
    });

    saveProfile();

    Map<String, dynamic> payload = {
      'data': AesHelper.aesEncrypt(
        widget.profile.symmetricKey!,
        Uint8List.fromList(widget.profile.image!.readAsBytesSync())
      ),
      'mimetype': lookupMimeType(widget.profile.image!.path),
      'extension': getExtension(widget.profile.image!.path),
    };

    http.post(
      await MyProfile.getServerUrl('api/v1/auth/image'),
      headers: {
        'cookie': await getSessionCookie(),
      },
      body: jsonEncode(payload),
    ).then((http.Response response) {
      if (response.statusCode == 204) {
        return;
      }

      showMessage(
        'Could not add profile picture, please try again later.',
        context,
      );
    });
  }

  Widget logout() {
    bool isTesting = dotenv.env['ENVIRONMENT'] == 'development';

    return Align(
        alignment: Alignment.centerLeft,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
             TextButton.icon(
                label: const Text(
                    'Logout',
                    style: TextStyle(fontSize: 16)
                ),
                icon: const Icon(Icons.exit_to_app),
                style: const ButtonStyle(
                    alignment: Alignment.centerLeft,
                ),
                onPressed: () {
                  deleteDb();
                  MyProfile.logout();
                  Navigator.pushNamedAndRemoveUntil(context, '/landing', ModalRoute.withName('/landing'));
                }
            ),
            isTesting ? TextButton.icon(
                label: const Text(
                    'Delete Database',
                    style: TextStyle(fontSize: 16)
                ),
                icon: const Icon(Icons.delete_forever),
                style: const ButtonStyle(
                    alignment: Alignment.centerLeft,
                ),
                onPressed: () {
                  deleteDb();
                }
            ) : const SizedBox.shrink(),
          ],
      ),
    );
  }

  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.profile.messageExpiryDefault,
                    backCallback: (String messageExpiry) async {
                      widget.profile.messageExpiryDefault = messageExpiry;

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

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

                      saveProfile();
                    },
                ))
              );
            }
          ),

          const SizedBox(height: 5),

          TextButton.icon(
            label: const Text(
              'Server URL',
              style: TextStyle(fontSize: 16)
            ),
            icon: const Icon(Icons.dataset_linked_outlined),
            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) => const ChangeServerUrl())
              );
            }
          ),

          const SizedBox(height: 5),

          TextButton.icon(
            label: const Text(
              'Change Password',
              style: TextStyle(fontSize: 16)
            ),
            icon: const Icon(Icons.password),
            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) => ChangePassword(
                    privateKey: widget.profile.privateKey!,
                ))
              );
              saveProfile();
            }
          ),
        ],
      ),
    );
  }

  Widget _profileQrCode() {
    String payload = jsonEncode({
      'i': widget.profile.id,
      'u': widget.profile.username,
      'k': base64.encode(
        CryptoUtils.encodeRSAPublicKeyToPem(widget.profile.publicKey!).codeUnits
      ),
    });

    return Column(
      children: [
        Padding(
          padding: const EdgeInsets.all(20),
          child: QrImage(
            backgroundColor: Theme.of(context).colorScheme.primary,
            data: payload,
            version: QrVersions.auto,
            gapless: true,
          ),
        ),
        Align(
          alignment: Alignment.centerRight,
          child: Padding(
            padding: const EdgeInsets.only(right: 20),
            child: IconButton(
              onPressed: () => _panelController.close(),
              icon: const Icon(Icons.arrow_upward),
            ),
          ),
        ),
      ]
    );
  }

  Future<void> saveProfile() async {
    final preferences = await SharedPreferences.getInstance();
    preferences.setString('profile', widget.profile.toJson());
  }
}
