import 'package:drifter/models/nip19/nip19_api.dart';
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:drifter/models/keys.dart';
import 'package:drifter/theme/app_colors.dart';
import 'package:dart_nostr/dart_nostr.dart';
// import 'package:nostr_tools/nostr_tools.dart';

import 'profile_screen_widgets/delete_keys_dialog.dart';
import 'profile_screen_widgets/key_exist_dialog.dart';
import 'profile_screen_widgets/keys_option_modal_bottom_sheet.dart';
import 'profile_screen_widgets/message_snack_bar.dart';
import 'profile_screen_widgets/user_info_widget.dart';

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

  @override
  State<ProfileScreen> createState() => ProfileScreenState();
}

class ProfileScreenState extends State<ProfileScreen> {
  final _secureStorage = const FlutterSecureStorage();

  TextEditingController privateKeyInput = TextEditingController();
  TextEditingController publicKeyInput = TextEditingController();

  // final keyGenerator = KeyApi();
  final nip19 = Nip19();

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

  Future<bool> generateNewKeys() async {
    final newPrivateKey = await Nostr.instance.keysService.generatePrivateKey();
    // final newPrivateKey = keyGenerator.generatePrivateKey();
    final nsec = nip19.nsecEncode(newPrivateKey);
    final nsecDecoded = nip19.decode(nsec);
    assert(nsecDecoded['type'] == 'nsec');
    assert(nsecDecoded['data'] == newPrivateKey);

    final newPublicKey = await Nostr.instance.keysService
        .derivePublicKey(privateKey: newPrivateKey);
    // final newPublicKey = keyGenerator.getPublicKey(newPrivateKey);
    final npub = nip19.npubEncode(newPublicKey);
    final npubDecoded = nip19.decode(npub);
    assert(npubDecoded['type'] == 'npub');
    assert(npubDecoded['data'] == newPublicKey);
    return await _addKeyToStorage(newPrivateKey, newPublicKey, nsec, npub);
  }

  Future<void> _getKeysFromStorage() async {
    // Reading values associated with the " privateKey " and " publicKey " keys from a secure repository
    final storedPrivateKey = await _secureStorage.read(key: 'privateKey');
    final storedPublicKey = await _secureStorage.read(key: 'publicKey');
    final storedNsecKey = await _secureStorage.read(key: 'nsec');
    final storedNpubKey = await _secureStorage.read(key: 'npub');
    // Indicates that both private and public keys are stored in a secure repository, after which, the state variables are updated
    if (storedPrivateKey != null &&
        storedPublicKey != null &&
        storedNsecKey != null &&
        storedNpubKey != null) {
      setState(() {
        Keys.privateKey = storedPrivateKey;
        Keys.publicKey = storedPublicKey;
        Keys.nsecKey = storedNsecKey;
        Keys.npubKey = storedNpubKey;
        Keys.keysExist = true;
      });
    }
  }

  // Adding a new key
// Writing a private and public key to a secure vault
  Future<bool> _addKeyToStorage(
    String privateKeyHex,
    String publicKeyHex,
    String nsecKey,
    String npubKey,
  ) async {
// Waiting for both write operations to complete
    Future.wait([
      _secureStorage.write(key: 'privateKey', value: privateKeyHex),
      _secureStorage.write(key: 'publicKey', value: privateKeyHex),
      _secureStorage.write(key: 'nsec', value: nsecKey),
      _secureStorage.write(key: 'npub', value: npubKey),
    ]);

    // Updating status variables and starting widget rebuilding
    setState(() {
      Keys.privateKey = privateKeyHex;
      Keys.publicKey = publicKeyHex;
      Keys.nsecKey = nsecKey;
      Keys.npubKey = npubKey;
      Keys.keysExist = true;
    });

// Returns a boolean value indicating whether the keys were successfully added to the repository or not.
    return Keys.keysExist;
  }

  Future<void> _deleteKeysStorage() async {
    // Calling secure storage to remove keys from storage
    Future.wait([
      _secureStorage.delete(key: 'privateKey'),
      _secureStorage.delete(key: 'publicKey'),
      _secureStorage.delete(key: 'nsec'),
      _secureStorage.delete(key: 'npub'),
    ]);

    // Updating status variables, resetting values after deleting keys from the repository
    setState(() {
      Keys.privateKey = '';
      Keys.publicKey = '';
      Keys.nsecKey = '';
      Keys.npubKey = '';
      Keys.keysExist = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    privateKeyInput.text = Keys.nsecKey;
    publicKeyInput.text = Keys.npubKey;

    return ListView(
      children: [
        SizedBox(
          height: 60,
        ),
        UserInfo(),
        SizedBox(
          height: 40,
        ),
        FormKeys(),
        SizedBox(height: 20),
        Padding(
          padding: const EdgeInsets.all(16.0),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: [
              Keys.keysExist
                  ? ElevatedButton(
                      style: ButtonStyle(
                          backgroundColor: MaterialStateProperty.all(
                              AppColors.mainDarkBlue)),
                      onPressed: () {
                        keysExistDialog(
                          nip19.npubEncode(Keys.publicKey),
                          nip19.nsecEncode(Keys.privateKey),
                        );
                      },
                      child: Text(
                        'Keys',
                      ),
                    )
                  : ElevatedButton(
                      style: ButtonStyle(
                          backgroundColor: MaterialStateProperty.all(
                              AppColors.mainDarkBlue)),
                      onPressed: () {
                        modalBottomSheet();
                      },
                      child: Text(
                        'Generate Keys',
                      ),
                    ),
              Keys.keysExist
                  ? Row(
                      children: [
                        IconButton(
                            onPressed: () {
                              deleteKeysDialog();
                            },
                            icon: const Icon(Icons.delete)),
                      ],
                    )
                  : Container(),
            ],
          ),
        )
      ],
    );
  }

  Form FormKeys() {
    return Form(
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextFormField(
              controller: privateKeyInput,
              // _toHex ? widget.hexPriv : widget.nsecEncoded,

              decoration: const InputDecoration(
                labelText: 'Private Key',
                border: OutlineInputBorder(),
              ),
              maxLength: 64,
            ),
            const SizedBox(
              height: 20,
            ),
            TextFormField(
              controller: publicKeyInput,
              //  _toHex ? widget.hexPub : widget.npubEncoded,
              decoration: const InputDecoration(
                labelText: 'Public Key',
                border: OutlineInputBorder(),
              ),
            ),
            const SizedBox(
              height: 40,
            ),
            TextFormField(
              decoration: const InputDecoration(
                labelText: 'Relay',
                border: OutlineInputBorder(),
              ),
            ),
          ],
        ),
      ),
    );
  }

  void modalBottomSheet() {
    showModalBottomSheet(
        context: context,
        builder: (BuildContext context) {
          return KeysOptionModalBottomSheet(
            generateNewKeyPressed: () {
              final currentContext = context;
              generateNewKeys().then(
                (keysGenerated) {
                  if (keysGenerated) {
                    ScaffoldMessenger.of(currentContext).showSnackBar(
                        MessageSnackBar(label: 'Keys Generated!'));
                  }
                },
              );
              Navigator.pop(context);
            },
          );
        });
  }

  void keysExistDialog(String npubEncode, String nsecEncode) async {
    await showDialog(
      context: context,
      builder: ((context) {
        return KeysExistDialog(
          npubEncoded: npubEncode,
          nsecEncoded: nsecEncode,
          hexPriv: Keys.privateKey,
          hexPub: Keys.publicKey,
        );
      }),
    );
  }

  void deleteKeysDialog() async {
    await showDialog(
      context: context,
      builder: ((context) {
        return DeleteKeysDialog(
          onNoPressed: () {
            Navigator.pop(context);
          },
          onYesPressed: () {
            final currentContext = context;
            _deleteKeysStorage().then((_) {
              if (!Keys.keysExist) {
                ScaffoldMessenger.of(currentContext).showSnackBar(
                  MessageSnackBar(
                    label: 'Keys successfully deleted!',
                    isWarning: true,
                  ),
                );
              }
            });
            Navigator.pop(context);
          },
        );
      }),
    );
  }
}