# AUTOGENERATED! DO NOT EDIT! File to edit: ../../notebooks/CLI_Token.ipynb.

# %% auto 0
__all__ = ['logger']

# %% ../../notebooks/CLI_Token.ipynb 3
from typing import *

# %% ../../notebooks/CLI_Token.ipynb 4
import os
import typer
import logging
import time
from datetime import datetime, timedelta

from airt.client import Client, User
from airt.logger import get_logger, set_level
from airt.constant import (
    SERVER_URL,
    SERVICE_USERNAME,
    SERVICE_PASSWORD,
    CLIENT_NAME,
    SERVICE_TOKEN,
)
from airt.cli import helper

# %% ../../notebooks/CLI_Token.ipynb 6
SESSION_TIME_LIMIT = 10  # mins

# %% ../../notebooks/CLI_Token.ipynb 7
app = typer.Typer()

# %% ../../notebooks/CLI_Token.ipynb 9
logger = get_logger(__name__)

# %% ../../notebooks/CLI_Token.ipynb 12
@helper.requires_totp_or_otp(
    message_template_name="get_token", requires_auth_token=False
)
def token(
    username: Optional[str] = typer.Option(
        None,
        "--username",
        "-u",
        help="Username for the developer account. If None (default value), then the value from"
        f" **{SERVICE_USERNAME}** environment variable is used.",
    ),
    password: Optional[str] = typer.Option(
        None,
        "--password",
        "-p",
        help="Password for the developer account. If None (default value), then the value from"
        f" **{SERVICE_PASSWORD}** environment variable is used.",
    ),
    server: Optional[str] = typer.Option(
        None,
        "--server",
        "-s",
        help=f"The {CLIENT_NAME} server uri. If None (default value), then the value from **{SERVER_URL}** environment variable"
        " is used. If the variable is not set as well, then the default public server will be used. Please leave this"
        f" setting to default unless you are running the service in your own server (please email us to info@{CLIENT_NAME}.ai"
        " for that possibility).",
    ),
    otp: Optional[str] = typer.Option(
        None,
        "--otp",
        help=f"Dynamically generated six-digit verification code from the authenticator app or the OTP you have received via SMS."
        " Please do not pass this parameter if you haven't enabled the multi-factor authentication for your account.",
    ),
    sso_provider: Optional[str] = typer.Option(
        None,
        "--sso_provider",
        "-sp",
        help=f"Name of the Single sign-on (SSO) provider. At the moment, we only support google and github as SSO providers."
        " Please pass this parameter only if you have successfully enabled SSO for the provider.",
    ),
    quiet: bool = typer.Option(
        False,
        "--quiet",
        "-q",
        help="Output authentication token only.",
    ),
    debug: bool = typer.Option(
        False, "--debug", "-d", help="Set logger level to DEBUG and output everything."
    ),
) -> None:
    """Get application token for airt service from a username/password pair.

    To access the airt service, you must first create a developer account. To obtain one, please contact us at info@airt.ai.

    After successful verification, you will receive an email with the username and password for the developer account.

    Once you have the credentials, use them to get an access token by running **airt token** command. It is necessary to
    get an access token; otherwise, you won't be able to access all of the airt service's APIs. You can either pass the
    username, password, and server address as command line arguments or store them in the environment variables
    **AIRT_SERVICE_USERNAME**, **AIRT_SERVICE_PASSWORD**, and **AIRT_SERVER_URL**.

    If you've already enabled multi-factor authentication (MFA) for your account, you'll need to pass the dynamically
    generated six-digit verification code along with your username and password to generate new tokens.

    If the token is requested using Single sign-on (SSO), an authorization URL will be returned. Please copy and paste
    it into your preferred browser and complete the SSO provider authentication within 10 minutes. Otherwise,
    the SSO login will time out and you will need to re-request the token.

    Single sign-on (SSO) can be enabled for your account in three simple steps:

    1. Enable the SSO for a provider by calling the command `airt user sso enable` with the SSO provider name and an email address.
    At the moment, we only support "google" and "github" as SSO providers. We intend to support additional SSO providers in future releases.

    2. Before you can start generating new tokens with SSO, you must first authenticate with the SSO provider. Call the `airt token` command with
    the same SSO provider you have enabled in the step above to generate an SSO authorization URL. Please copy and paste it into your
    preferred browser and complete the authentication process with the SSO provider.

    3. After successfully authenticating with the SSO provider, an access token will be generated and returned. Please set it in the
    **AIRT_SERVICE_TOKEN** environment variable for accessing the airt service.
    """
    try:
        if debug:
            set_level(logging.DEBUG)
        else:
            set_level(logging.WARNING)

        if sso_provider is None:
            Client.get_token(
                username=username, password=password, server=server, otp=otp
            )

            if quiet:
                typer.echo(Client.auth_token)
            else:
                typer.echo(f"token: {Client.auth_token}")

        else:
            authorization_url = Client.get_token(
                username=username,
                password=password,
                server=server,
                otp=otp,
                sso_provider=sso_provider,
            )

            typer.echo(
                "\nPlease copy and paste the authorization URL below into your preferred browser and complete the SSO provider authentication "
                "within 10 minutes. Otherwise, the SSO login will time out and you will have to re-run the token command."
            )

            typer.echo(f"\n\n{authorization_url}\n")

            typer.echo(
                f"\nAfter successfully authenticating with the SSO provider, an access token will be returned. Please set it in the {SERVICE_TOKEN} "
                f"environment variable for accessing the `{CLIENT_NAME}` service."
            )

            typer.echo(
                "\nIf there are any errors, an error message will be displayed in the terminal and this command will be terminated.\n"
            )

            end_time = datetime.utcnow() + timedelta(minutes=SESSION_TIME_LIMIT)
            while datetime.utcnow() < end_time:
                err = None
                try:
                    Client.set_sso_token()
                    typer.echo(
                        f"\nSSO authentication is successful, please set the below token in the `{SERVICE_TOKEN}` environment variable for accessing the `{CLIENT_NAME}` service.\n"
                    )
                    typer.echo(f"{Client.auth_token}\n")
                    break
                except ValueError as e:
                    err = str(e)
                    if "SSO authentication is not complete" not in str(e):
                        raise ValueError(f"\n{e}")
                time.sleep(1)
            if err is not None:
                raise ValueError(
                    f"\nYour session has expired. Please call the {CLIENT_NAME} token command with the sso provider and try again."
                )

        if not quiet:
            details = User.details()
            status = helper.get_phone_registration_status(details)
            if status is not None:
                typer.echo(status)

    except KeyError as e:
        typer.echo(message=f"Error: {e}", err=True)
        typer.echo(f"\nTry '{CLIENT_NAME} token --help' for help.")
        raise typer.Exit(code=1)

    except Exception as e:
        typer.echo(message=f"Error: {e}", err=True)
        if ("Invalid OTP" in str(e)) or ("OTP is required" in str(e)):
            raise ValueError(e)
        raise typer.Exit(code=1)

# %% ../../notebooks/CLI_Token.ipynb 13
app.command()(token)
