from getpass import getpass

import click
from click import echo, secho

import code42cli.profile as cliprofile
from code42cli.errors import Code42CLIError
from code42cli.profile import CREATE_PROFILE_HELP
from code42cli.sdk_client import validate_connection
from code42cli.util import does_user_agree


@click.group()
def profile():
    """For managing Code42 settings."""
    pass


profile_name_arg = click.argument("profile_name", required=False)
name_option = click.option(
    "-n",
    "--name",
    required=True,
    type=str,
    help="The name of the Code42 CLI profile to use when executing this command.",
)
server_option = click.option(
    "-s", "--server", required=True, type=str, help="The url and port of the Code42 server."
)
username_option = click.option(
    "-u", "--username", required=True, type=str, help="The username of the Code42 API user."
)
disable_ssl_option = click.option(
    "--disable-ssl-errors",
    is_flag=True,
    help="For development purposes, do not validate the SSL certificates of Code42 servers. "
    "This is not recommended unless it is required.",
)


@profile.command()
@profile_name_arg
def show(profile_name):
    """Print the details of a profile."""
    c42profile = cliprofile.get_profile(profile_name)
    echo("\n{0}:".format(c42profile.name))
    echo("\t* username = {}".format(c42profile.username))
    echo("\t* authority url = {}".format(c42profile.authority_url))
    echo("\t* ignore-ssl-errors = {}".format(c42profile.ignore_ssl_errors))
    if cliprofile.get_stored_password(c42profile.name) is not None:
        echo("\t* A password is set.")
    echo("")
    echo("")


@profile.command()
@name_option
@server_option
@username_option
@disable_ssl_option
def create(name, server, username, disable_ssl_errors=False):
    """Create profile settings. The first profile created will be the default."""
    cliprofile.create_profile(name, server, username, disable_ssl_errors)
    _prompt_for_allow_password_set(name)
    echo("Successfully created profile '{}'.".format(name))


@profile.command()
@name_option
@server_option
@username_option
@disable_ssl_option
def update(name=None, server=None, username=None, disable_ssl_errors=None):
    """Update an existing profile."""
    profile = cliprofile.get_profile(name)
    cliprofile.update_profile(profile.name, server, username, disable_ssl_errors)
    _prompt_for_allow_password_set(profile.name)
    echo("Profile '{}' has been updated.".format(profile.name))


@profile.command()
@profile_name_arg
def reset_pw(profile_name=None):
    """Change the stored password for a profile."""
    _reset_pw(profile_name)


@profile.command("list")
def _list():
    """Show all existing stored profiles."""
    profiles = cliprofile.get_all_profiles()
    if not profiles:
        raise Code42CLIError("No existing profile.", help=CREATE_PROFILE_HELP)
    for profile in profiles:
        echo(str(profile))


@profile.command()
@profile_name_arg
def use(profile_name):
    """Set a profile as the default."""
    cliprofile.switch_default_profile(profile_name)


@profile.command()
@profile_name_arg
def delete(profile_name):
    """Deletes a profile and its stored password (if any)."""
    if cliprofile.is_default_profile(profile_name):
        echo("\n{} is currently the default profile!".format(profile_name))
    if not does_user_agree(
        "\nDeleting this profile will also delete any stored passwords and checkpoints. "
        "Are you sure? (y/n): "
    ):
        return
    cliprofile.delete_profile(profile_name)
    echo("Profile '{}' has been deleted.".format(profile_name))


@profile.command()
def delete_all():
    """Deletes all profiles and saved passwords (if any)."""
    existing_profiles = cliprofile.get_all_profiles()
    if existing_profiles:
        echo("\nAre you sure you want to delete the following profiles?")
        for profile in existing_profiles:
            echo("\t{}".format(profile.name))
        if does_user_agree("\nThis will also delete any stored passwords and checkpoints. (y/n): "):
            for profile in existing_profiles:
                cliprofile.delete_profile(profile.name)
                echo("Profile '{}' has been deleted.".format(profile.name))
    else:
        echo("\nNo profiles exist. Nothing to delete.")


def _prompt_for_allow_password_set(profile_name):
    if does_user_agree("Would you like to set a password? (y/n): "):
        _reset_pw(profile_name)


def _reset_pw(profile_name):
    c42profile = cliprofile.get_profile(profile_name)
    new_password = getpass()
    try:
        validate_connection(c42profile.authority_url, c42profile.username, new_password)
    except Exception:
        secho("Password not stored!", bold=True)
        raise
    cliprofile.set_password(new_password, c42profile.name)
