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

__all__ = ["logger"]

# Cell

from typing import *

# Internal Cell

import os
import typer
import logging
import time
from datetime import datetime, timedelta

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

# Internal Cell

SESSION_TIME_LIMIT = 10  # mins

# Internal Cell

app = typer.Typer()

# Cell

logger = get_logger(__name__)

# Internal Cell


@helper.requires_otp()
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[int] = typer.Option(
        None,
        "--otp",
        help=f"Dynamically generated six-digit verification code from the authenticator app. 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. Please pass this parameter only if you have successfully"
        " enabled SSO for this 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 create a developer account. Please contact us by email info@airt.ai to get one.

    Finally, you need an application token to access all the APIs in airt service. Please run the command **airt token**
    with the username/password to get one. You can either pass the username, password, and server address as command line
    arguments or store them in the **AIRT_SERVICE_USERNAME**, **AIRT_SERVICE_PASSWORD**, and **AIRT_SERVER_URL** environment variables.

    In case of MFA enabled user, along with the username/password the dynamically generated six-digit verification code
    also needs to be passed when requesting an auth token.

    You can also enable Single sign-on (SSO) for your account and generate tokens. Currently, we support only Google and Github
    as the external authentication providers (SSO). More authentication providers will be supported in the upcoming releases.

    Authenticating using Single sign-on (SSO) is also a three-step process:

    1. Enable the SSO provider by calling the command `airt user sso enable` method with a valid SSO provider and an email address.

    2. In order to get the token, you must have to complete the SSO authentication with the provider. Calling the command `airt token` with a valid SSO provider will give you an authorization URL. Please copy and paste it into your preferred browser and initiate the authentication process with the SSO provider.

    3. Once the authentication is successful, an access token will be generated and will be returned.

    Upon receiving the application token, please set it in the environment variable **AIRT_SERVICE_TOKEN** 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(
                "\nAttempting to automatically open the SSO authorization URL in your default browser."
            )

            typer.echo(
                "\nIf the browser does not open, please copy the below authorization URL and open it in your preferred browser."
            )

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

            typer.echo(
                "\nAn access token will be returned if the SSO authentication is successful and completed within 10 minutes."
            )

            typer.echo(
                "\nIn case of any errors, a respective error message will be displayed in the terminal and this command will terminate.\n"
            )

            # Automatically launching the browser
            server = os.environ.get(SERVER_URL, None)
            if (server is None) or ("airt-service" not in server):
                typer.launch(authorization_url)  # type: ignore

            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 and proceed.\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."
                )

    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)


# Internal Cell


app.command()(token)
