from getpass import getpass
from pathlib import Path

import click
import securesystemslib
from securesystemslib.interface import (
    import_rsa_privatekey_from_file,
    import_rsa_publickey_from_file,
)
from taf.constants import DEFAULT_RSA_SIGNATURE_SCHEME
from taf.exceptions import KeystoreError
from tuf.repository_tool import import_rsakey_from_pem


def _form_private_pem(pem):
    return f"-----BEGIN RSA PRIVATE KEY-----\n{pem}\n-----END RSA PRIVATE KEY-----"


def key_cmd_prompt(
    key_name, role, taf_repo, loaded_keys=None, scheme=DEFAULT_RSA_SIGNATURE_SCHEME
):
    def _enter_and_check_key(key_name, role, loaded_keys, scheme):
        pem = getpass(f"Enter {key_name} private key without its header and footer\n")
        pem = _form_private_pem(pem)
        try:
            key = import_rsakey_from_pem(pem, scheme)
        except Exception:
            print("Invalid key")
            return None
        public_key = import_rsakey_from_pem(key["keyval"]["public"], scheme)
        if not taf_repo.is_valid_metadata_yubikey(role, public_key):
            print(f"The entered key is not a valid {role} key")
            return None
        if loaded_keys is not None and key in loaded_keys:
            print("Key already entered")
            return None
        return key

    while True:
        key = _enter_and_check_key(key_name, role, loaded_keys, scheme)
        if key is not None:
            return key


def load_tuf_private_key(key_str, key_name, scheme=DEFAULT_RSA_SIGNATURE_SCHEME):
    if not key_str:
        key_str = getpass(
            f"Enter {key_name} private key without its header and footer\n"
        )
    key_pem = _form_private_pem(key_str)

    return import_rsakey_from_pem(key_pem, scheme)


def read_private_key_from_keystore(
    keystore,
    key_name,
    roles_key_info=None,
    key_num=None,
    scheme=DEFAULT_RSA_SIGNATURE_SCHEME,
):
    key_path = Path(keystore, key_name)
    if not key_path.is_file():
        raise KeystoreError(f"{str(key_path)} does not exist")

    password = None
    if roles_key_info is not None:
        passwords = roles_key_info.get("passwords")
        if passwords is not None and len(passwords):
            password = passwords[key_num]

    def _read_key(path, password):
        if password is None:
            password = getpass(
                f"Enter {key_name} keystore file password and press ENTER"
            )
        if not password:
            password = None
        try:
            return import_rsa_privatekey_from_file(
                str(Path(keystore, key_name)), password, scheme=scheme
            )
        except (
            securesystemslib.exceptions.FormatError,
            securesystemslib.exceptions.Error,
        ) as e:
            if "password" in str(e).lower():
                return None
            raise KeystoreError(e)
        except Exception:
            return None

    while True:
        key = _read_key(key_path, password)
        if key is not None:
            return key
        if not click.confirm("Could not open keystore file. Try again?"):
            raise KeystoreError(f"Could not open keystore file {key_path}")


def read_public_key_from_keystore(
    keystore, key_name, scheme=DEFAULT_RSA_SIGNATURE_SCHEME
):
    pub_key_path = Path(keystore, f"{key_name}.pub")
    if not pub_key_path.is_file():
        raise KeystoreError(f"{str(pub_key_path)} does not exist")
    try:
        return import_rsa_publickey_from_file(str(pub_key_path), scheme)
    except (
        securesystemslib.exceptions.FormatError,
        securesystemslib.exceptions.Error,
    ) as e:
        raise KeystoreError(e)
