# AUTOGENERATED! DO NOT EDIT! File to edit: notebooks/CLI_User.ipynb (unless otherwise specified).

__all__ = ["logger"]

# Cell

from typing import *

# Internal Cell

import os

import typer
from typer import echo
from tabulate import tabulate
import datetime as dt
import pandas as pd
import qrcode

from ..client import Client
from . import helper
from ..logger import get_logger, set_level

# Internal Cell

app = typer.Typer(
    help="A set of commands for managing users and their authentication in the server."
)

# Cell

logger = get_logger(__name__)

# Internal Cell


@app.command()
@helper.display_formated_table
@helper.requires_otp()
@helper.requires_auth_token
def details(
    user: Optional[str] = typer.Option(
        None,
        "--user",
        "-u",
        help="Account user_uuid/username to get details. If not passed, then the currently logged-in details will be returned.",
    ),
    otp: Optional[str] = typer.Option(
        None,
        "--otp",
        help="Dynamically generated six-digit verification code from the authenticator app. Please pass this optional argument only if the MFA is enabled for your account.",
    ),
    format: Optional[str] = typer.Option(
        None,
        "--format",
        "-f",
        help="Format output and show only the given column(s) values.",
    ),
    quiet: bool = typer.Option(
        False,
        "--quiet",
        "-q",
        help="Output user uuid only.",
    ),
) -> Dict["str", Union[pd.DataFrame, str]]:
    """Get user details

    Please do not pass the optional 'user' option unless you are a super user. Only a super user can view details for other users.
    """

    from ..client import User

    df = pd.DataFrame(User.details(user=user, otp=otp), index=[0])[User.USER_COLS]

    return {"df": df}


# Internal Cell


@app.command()
@helper.display_formated_table
@helper.requires_otp()
@helper.requires_auth_token
def create(
    username: str = typer.Option(
        ..., "--username", "-un", help="The username for the new user."
    ),
    first_name: str = typer.Option(
        ...,
        "--first_name",
        "-fn",
        help="The first name for the new user.",
    ),
    last_name: str = typer.Option(
        ...,
        "--last_name",
        "-ln",
        help="The last name for the new user.",
    ),
    email: str = typer.Option(
        ...,
        "--email",
        "-e",
        help="The email for the new user.",
    ),
    password: str = typer.Option(
        ...,
        "--password",
        "-p",
        help="The password for the new user.",
    ),
    subscription_type: str = typer.Option(
        ...,
        "--subscription_type",
        "-st",
        help="User subscription type. Currently, the API supports only the following subscription types **small**, **medium** and **large**.",
    ),
    super_user: bool = typer.Option(
        False,
        "--super_user",
        "-su",
        help="If set to **True**, then the new user will have super user privilages. If **None**, then the default value "
        "**False** will be used to create a non-super user.",
    ),
    otp: Optional[str] = typer.Option(
        None,
        "--otp",
        help="Dynamically generated six-digit verification code from the authenticator app. Please pass this optional argument only if the MFA is enabled for your account.",
    ),
    format: Optional[str] = typer.Option(
        None,
        "--format",
        "-f",
        help="Format output and show only the given column(s) values.",
    ),
    quiet: bool = typer.Option(
        False,
        "--quiet",
        "-q",
        help="Output user uuid only.",
    ),
    debug: bool = typer.Option(
        False,
        "--debug",
        "-d",
        help="Set logger level to DEBUG and output everything.",
    ),
) -> Dict["str", Union[pd.DataFrame, str]]:
    """Create a new user in the server."""

    from ..client import User

    df = User.create(
        username=username,
        first_name=first_name,
        last_name=last_name,
        email=email,
        subscription_type=subscription_type,
        super_user=super_user,
        password=password,
        otp=otp,
    )

    df["created"] = helper.humanize_date(df["created"])

    return {"df": df}


# Internal Cell


@app.command()
@helper.display_formated_table
@helper.requires_otp()
@helper.requires_auth_token
def ls(
    offset: int = typer.Option(
        0,
        "--offset",
        "-o",
        help="The number of users to offset at the beginning. If **None**, then the default value **0** will be used.",
    ),
    limit: int = typer.Option(
        100,
        "--limit",
        "-l",
        help="The maximum number of users to return from the server. If None, then the default value 100 will be used.",
    ),
    disabled: bool = typer.Option(
        False,
        "--disabled",
        help="If set to **True**, then only the deleted users will be returned. Else, the default value **False** will "
        "be used to return only the list of active users.",
    ),
    otp: Optional[str] = typer.Option(
        None,
        "--otp",
        help="Dynamically generated six-digit verification code from the authenticator app. Please pass this optional argument only if the MFA is enabled for your account.",
    ),
    format: Optional[str] = typer.Option(
        None,
        "--format",
        "-f",
        help="Format output and show only the given column(s) values.",
    ),
    quiet: bool = typer.Option(
        False,
        "--quiet",
        "-q",
        help="Output only user uuids separated by space",
    ),
    debug: bool = typer.Option(
        False,
        "--debug",
        "-d",
        help="Set logger level to DEBUG and output everything.",
    ),
) -> Dict["str", Union[pd.DataFrame, str]]:
    """Return the list of users available in the server."""

    from ..client import User

    ux = User.ls(offset=offset, limit=limit, disabled=disabled, otp=otp)

    df = User.as_df(ux)

    df["created"] = helper.humanize_date(df["created"])

    return {"df": df}


# Internal Cell


@app.command()
@helper.display_formated_table
@helper.requires_otp()
@helper.requires_auth_token
def disable(
    users: List[str] = typer.Argument(
        ...,
        help="user_uuid/username to disabled.  To disable multiple users, please pass the uuids/names separated by space.",
    ),
    otp: Optional[str] = typer.Option(
        None,
        "--otp",
        help="Dynamically generated six-digit verification code from the authenticator app. Please pass this optional argument only if the MFA is enabled for your account.",
    ),
    format: Optional[str] = typer.Option(
        None,
        "--format",
        "-f",
        help="Format output and show only the given column(s) values.",
    ),
    quiet: bool = typer.Option(
        False,
        "--quiet",
        "-q",
        help="Output user uuid only.",
    ),
    debug: bool = typer.Option(
        False,
        "--debug",
        "-d",
        help="Set logger level to DEBUG and output everything.",
    ),
) -> Dict["str", Union[pd.DataFrame, str]]:
    """Disable a user in the server."""

    from ..client import User

    users = [user for user in users]
    #     formated_users = helper.separate_integers_and_strings(users)

    df = User.disable(user=users, otp=otp)  # type: ignore
    df["created"] = helper.humanize_date(df["created"])

    return {"df": df}


# Internal Cell


@app.command()
@helper.display_formated_table
@helper.requires_otp()
@helper.requires_auth_token
def enable(
    users: List[str] = typer.Argument(
        ...,
        help="user_uuid/username to enable. To enable multiple users, please pass the uuids/names separated by space.",
    ),
    otp: Optional[str] = typer.Option(
        None,
        "--otp",
        help="Dynamically generated six-digit verification code from the authenticator app. Please pass this optional argument only if the MFA is enabled for your account.",
    ),
    format: Optional[str] = typer.Option(
        None,
        "--format",
        "-f",
        help="Format output and show only the given column(s) values.",
    ),
    quiet: bool = typer.Option(
        False,
        "--quiet",
        "-q",
        help="Output user uuid only.",
    ),
    debug: bool = typer.Option(
        False,
        "--debug",
        "-d",
        help="Set logger level to DEBUG and output everything.",
    ),
) -> Dict["str", Union[pd.DataFrame, str]]:
    """Enable a disabled user in the server."""

    from ..client import User

    users = [user for user in users]
    #     formated_users = helper.separate_integers_and_strings(users)

    df = User.enable(user=users, otp=otp)  # type: ignore
    df["created"] = helper.humanize_date(df["created"])

    return {"df": df}


# Internal Cell


@app.command()
@helper.display_formated_table
@helper.requires_otp()
@helper.requires_auth_token
def update(
    user: Optional[str] = typer.Option(
        None,
        "--user",
        help="Account user_uuid/username to update. If not passed, then the default value None will be used to update the currently logged-in user details.",
    ),
    username: Optional[str] = typer.Option(
        None,
        "--username",
        "-un",
        help="New username for the user.",
    ),
    first_name: Optional[str] = typer.Option(
        None,
        "--first_name",
        "-fn",
        help="New first name for the user.",
    ),
    last_name: Optional[str] = typer.Option(
        None,
        "--last_name",
        "-ln",
        help="New last name for the user.",
    ),
    email: Optional[str] = typer.Option(
        None,
        "--email",
        "-e",
        help="New email for the user.",
    ),
    password: Optional[str] = typer.Option(
        None,
        "--password",
        "-p",
        help="New password for the user.",
    ),
    otp: Optional[str] = typer.Option(
        None,
        "--otp",
        help="Dynamically generated six-digit verification code from the authenticator app. Please pass this optional argument only if the MFA is enabled for your account.",
    ),
    format: Optional[str] = typer.Option(
        None,
        "--format",
        "-f",
        help="Format output and show only the given column(s) values.",
    ),
    quiet: bool = typer.Option(
        False,
        "--quiet",
        "-q",
        help="Output user uuid only.",
    ),
    debug: bool = typer.Option(
        False,
        "--debug",
        "-d",
        help="Set logger level to DEBUG and output everything.",
    ),
) -> Dict["str", Union[pd.DataFrame, str]]:
    """Update existing user details in the server.

    Please do not pass the optional user option unless you are a super user. Only a
    super user can update details for other users.

    """

    from ..client import User

    df = User.update(
        user=user,
        username=username,
        first_name=first_name,
        last_name=last_name,
        email=email,
        password=password,
        otp=otp,
    )

    df["created"] = helper.humanize_date(df["created"])

    return {"df": df}


# Internal Cell

mfa_app = typer.Typer(
    help="Commands for enabling and disabling Multi-Factor Authentication (MFA)."
)

# Internal Cell


@mfa_app.command()  # type: ignore
@helper.requires_otp()
@helper.requires_auth_token
def enable(
    otp: Optional[str] = typer.Option(
        None,
        "--otp",
        help="Dynamically generated six-digit verification code from the authenticator app. Please pass this optional argument only if the MFA is enabled for your account.",
    ),
) -> None:
    """Enable Multi-Factor Authentication (MFA) for the user.

    This is an interactive command and will generate a QR code. You can use an authenticator app, such as Google Authenticator
    to scan the code and enter the valid six-digit verification code from the authenticator app in the interactive prompt to
    enable and activate MFA for your account.

    After three invalid attempts, you have to call this command again to generate a new QR code.
    """

    from ..client import User

    qr = qrcode.QRCode()
    qr.add_data(User._get_mfa_provision_url(otp=otp))

    typer.echo("Please open an authenticator app and scan the QR code below:")
    #     typer.echo(qr.print_ascii(invert=True))
    typer.echo(qr.print_ascii())

    for i in range(3):

        try:
            activation_otp = typer.prompt(
                "Please enter the OTP displayed in the authenticator app"
            )
            response = User.activate_mfa(otp=activation_otp)
            typer.echo("Multi-Factor Authentication (MFA) successfully activated.")
            break

        except ValueError as e:
            typer.echo(e)


# Internal Cell


@mfa_app.command()  # type: ignore
@helper.requires_otp()
@helper.requires_auth_token
def disable(
    user: Optional[str] = typer.Option(
        None,
        "--user",
        "-u",
        help="Account user_uuid/username to disable MFA. If not passed, then the default value None will be used to disable MFA for the currently logged-in user.",
    ),
    otp: Optional[str] = typer.Option(
        None,
        "--otp",
        help="Dynamically generated six-digit verification code from the authenticator app. Please pass this optional argument only if the MFA is enabled for your account.",
    ),
) -> None:
    """Disable Multi-Factor Authentication (MFA) for the user.

    Please do not pass the user argument unless you are a super user. Only
    a super user can disable MFA for other users.
    """

    from ..client import User

    User.disable_mfa(user=user, otp=otp)

    typer.echo(
        "Multi-Factor Authentication (MFA) is successfully deactivated for the user."
    )


# Internal Cell

# Adding mfa as a subcommand for user command
app.add_typer(mfa_app, name="mfa")

# Internal Cell

sso_app = typer.Typer(help="Commands for enabling and disabling Single sign-on (SSO).")

# Internal Cell


@sso_app.command()  # type: ignore
@helper.requires_otp()
@helper.requires_auth_token
def disable(
    sso_provider: str = typer.Argument(
        ...,
        help="Name of the Single sign-on (SSO) identity provider.",
    ),
    user: Optional[str] = typer.Option(
        None,
        "--user",
        "-u",
        help="Account user_uuid/username to disable MFA. If not passed, then the default value None will be used to disable SSO for the currently logged-in user.",
    ),
    otp: Optional[str] = typer.Option(
        None,
        "--otp",
        help="Dynamically generated six-digit verification code from the authenticator app. Please pass this optional argument only if the MFA is enabled for your account.",
    ),
) -> None:
    """Disable Single sign-on (SSO) for the user.

    Please do not pass the user argument unless you are a super user. Only
    a super user can disable SSO for other users.
    """

    from ..client import User

    success_msg = User.disable_sso(sso_provider=sso_provider, user=user, otp=otp)
    typer.echo(success_msg)


# Internal Cell


@sso_app.command()  # type: ignore
@helper.requires_otp()
@helper.requires_auth_token
def enable(
    sso_provider: str = typer.Argument(
        ...,
        help="Name of the Single sign-on (SSO) identity provider.",
    ),
    sso_email: str = typer.Option(
        ...,
        "--email",
        "-e",
        help="Email id going to be used for SSO authentication.",
    ),
    otp: Optional[str] = typer.Option(
        None,
        "--otp",
        help="Dynamically generated six-digit verification code from the authenticator app. Please pass this optional argument only if the MFA is enabled for your account.",
    ),
) -> None:
    """Enable Single sign-on (SSO) for the user"""

    from ..client import User

    success_msg = User.enable_sso(
        sso_provider=sso_provider, sso_email=sso_email, otp=otp
    )

    typer.echo(success_msg)


# Internal Cell

# Adding sso as a subcommand for user command
app.add_typer(sso_app, name="sso")
