#!/usr/bin/env python
# encoding: utf-8
#
# Copyright (c) 2011 Duo Security
# All Rights Reserved
#

# This import _must_ be first
import _fipscustomize # noqa: F401, isort:skip

import argparse
import getpass
import os

from duoauthproxy.lib import path_util, protect
from duoauthproxy.lib.config_encryption import decrypt_config_file, encrypt_config_file


def confirm_update_whole_config(decrypt: bool) -> bool:
    """
    Prompts the user to confirm that they'd like to proceed with de/en/crypting
    the entire configuration file.

    Returns:
        True if the user wants to continue with whole-config de/en/cryption, false
        otherwise.
    """
    if decrypt:
        question = (
            "Using --whole-config will decrypt all passwords and secrets in "
            "your configuration file, overwriting the encrypted values "
            "in-place. Would you like to continue? [Yes/no]: "
        )
    else:
        question = (
            "Using --whole-config will encrypt all passwords and secrets in "
            "your configuration file, overwriting the plaintext values "
            "in-place. Would you like to continue? [Yes/no]: "
        )
    response = input(question).lower().strip()

    while response not in ("yes", "no", ""):
        response = input("Please enter 'yes' or 'no': ").lower().strip()

    if response in ("yes", ""):
        return True
    else:
        return False


def main():
    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawTextHelpFormatter,
        description=(
            "Duo Security Authentication Proxy Password Encryption Tool.\n\n"
            "This tool encrypts passwords and secrets which can then be used "
            "as values for _protected configuration options. By default, a "
            "single value to encrypt is taken from the command line and the "
            "encrypted result is printed. \n\n"
            "The encryption is done using machine credentials. Once encrypted, "
            "only the machine that performed the encryption can decrypt the values."
        ),
    )
    parser.add_argument(
        "--whole-config",
        dest="whole_config",
        action="store_true",
        default=False,
        help="Reads through the entire configuration file and encrypts or decrypts all password and secret fields",
    )

    parser.add_argument(
        "--yes",
        "-y",
        dest="yes_confirmed",
        action="store_true",
        default=False,
        help='Respond "yes" to all yes/no prompts',
    )

    parser.add_argument(
        "--yes-overwrite",
        dest="overwrite_config",
        action="store_true",
        default=False,
        help=argparse.SUPPRESS,
    )

    parser.add_argument(
        "--decrypt",
        dest="decrypt",
        action="store_true",
        default=False,
        help="Decrypts the existing secrets instead of encrypting them. Only works with --whole-config.",
    )

    parser.add_argument(
        "password",
        nargs="?",
        default="",
        help="The password or secret to encrypt. Has no effect if --whole-config is used.",
    )

    args = parser.parse_args()

    if args.overwrite_config:
        print(
            "--yes-overwrite is deprecated and has no effect. The Password Encryption Tool now preserves comments."
        )

    if args.whole_config:
        if args.yes_confirmed or confirm_update_whole_config(args.decrypt):
            try:
                home_dir = path_util.get_home_dir()
                os.chdir(home_dir)
                config_filename = os.path.join(home_dir, "conf", "authproxy.cfg")
                if args.decrypt:
                    decrypt_config_file(config_filename)
                    print(
                        "Decryption complete. The Authentication Proxy configuration file has been updated."
                    )
                else:
                    encrypt_config_file(config_filename)
                    print(
                        "Encryption complete. The Authentication Proxy configuration file has been updated."
                    )

            except Exception as e:
                print(
                    "Error encrypting/decrypting configuration file. No changes were made.\n\n{}".format(
                        e
                    )
                )
        else:
            print("Exiting. No changes were made.")
    else:
        if args.decrypt:
            print("Decryption is only allowed in --whole-config mode.")
            return
        if not args.password:
            print("Please provide your secret to encrypt.")

            password = getpass.getpass("Password:")
            password2 = getpass.getpass("Re-enter password:")
            if password != password2:
                print("Passwords do not match")
                return
        else:
            password = args.password
        protected_pw = protect.protect(password)
        print(protected_pw)


if __name__ == "__main__":
    main()
