from __future__ import annotations

import datetime

import typer

from remotivelabs.cli.topology.start_trial import (
    MissingOrganizationError,
    NoActiveAccountError,
    NoOrganizationOrPermissionError,
    NotAuthorizedError,
    NotAuthorizedToStartTrialError,
    NotSignedInError,
    Subscription,
    SubscriptionExpiredError,
    get_organization_and_account,
    start_trial,
)
from remotivelabs.cli.typer_ext import typer_utils
from remotivelabs.cli.utils.console import print_generic_error, print_generic_message, print_hint, print_unformatted
from remotivelabs.cli.utils.rest_helper import RestHelper

HELP = """
Manage RemotiveTopology subscriptions, you can start a trial subscription or check the status of your subscription.

To extend a trial subscription, or purchase a subscription, please contact support@remotivelabs.com.
"""

app = typer_utils.create_typer_sorted(rich_markup_mode="rich", help=HELP)


@app.command("start-trial")
def start_trial_cmd(  # noqa: C901
    organization: str = typer.Option(None, help="Organization to start trial for", envvar="REMOTIVE_CLOUD_ORGANIZATION"),
) -> None:
    """
    Allows you to start a 30 day trial subscription for running RemotiveTopology.

    You can read more at https://docs.remotivelabs.com/docs/remotive-topology.
    """

    try:
        (valid_organization, _) = get_organization_and_account(organization_uid=organization)
        ok_to_start_trial = typer.confirm(
            f"You are about to start trial of RemotiveTopology for {valid_organization.display_name}"
            f" (uid={valid_organization.uid}), continue?",
            default=True,
        )
        if not ok_to_start_trial:
            return

        (subscription, created) = start_trial(organization)

        def print_start_trial_result() -> None:
            assert subscription.type in ("trial", "paid"), f"Unexpected subscription type: {subscription.type}"
            kind = None
            status = None
            if subscription.type == "trial":
                status = "started now" if created else "is already active"
                kind = "trial subscription"
            elif subscription.type == "paid":
                status = "started now" if created else "is already started"
                kind = "subscription"

            end_text = subscription.end_date or "Never"
            print_generic_message(f"RemotiveTopology {kind} for {valid_organization.display_name} {status}, expires {end_text}")

        print_start_trial_result()

    except NotSignedInError:
        print_generic_error(
            "You must first sign in to RemotiveCloud, please use [bold]remotive cloud auth login[/bold] to sign-in"
            "This requires a RemotiveCloud account, if you do not have an account you can sign-up at https://cloud.remotivelabs.com"
        )
        raise typer.Exit(1)

    except NoActiveAccountError:
        print_hint(
            "You have not activated your account, please run [bold]remotive cloud auth activate[/bold] to choose an account"
            "or [bold]remotive cloud auth login[/bold] to sign-in"
        )
        raise typer.Exit(1)

    except NotAuthorizedError:
        print_hint(
            "Your current active credentials are not valid, please run [bold]remotive cloud auth login[/bold] to sign-in again."
            "This requires a RemotiveCloud account, if you do not have an account you can sign-up at https://cloud.remotivelabs.com"
        )
        raise typer.Exit(1)

    except MissingOrganizationError:
        print_hint("You have not specified any organization and no default organization is set")
        raise typer.Exit(1)

    except NotAuthorizedToStartTrialError as e:
        print_generic_error(f"You are not allowed to start-trial topology in organization {e.organization.display_name}.")
        raise typer.Exit(1)

    except SubscriptionExpiredError as e:
        if e.subscription.type == "trial":
            print_generic_error(
                f"RemotiveTopology trial in {e.organization.display_name} expired"
                f" {e.subscription.end_date}, please contact support@remotivelabs.com"
            )
            raise typer.Exit(1)

        print_generic_error(
            f"RemotiveTopology subscription in {e.organization.display_name} has expired"
            f" {e.subscription.end_date}, please contact support@remotivelabs.com"
        )
        raise typer.Exit(1)

    except NoOrganizationOrPermissionError as e:
        print_generic_error(f"Organization id {e.organization} does not exist or you do not have permission to access it.")
        raise typer.Exit(1)

    except Exception as e:
        print_generic_error(f"Unexpected error: {e}")
        raise typer.Exit(1)


@app.command("status")
def status_cmd(  # noqa: C901
    organization: str = typer.Option(None, help="Organization to check subscription status for", envvar="REMOTIVE_CLOUD_ORGANIZATION"),
) -> None:
    """
    Show the current RemotiveTopology subscription status for an organization.
    """

    try:
        (valid_organization, account) = get_organization_and_account(organization_uid=organization)

        res = RestHelper.handle_get(
            f"/api/bu/{valid_organization.uid}/features/topology",
            return_response=True,
            allow_status_codes=[403, 404],
        )

        if res.status_code == 403:
            print_generic_error(
                f"You do not have permission to view subscription status for {valid_organization.display_name}"
                + f" (id: {valid_organization.uid})."
            )
            raise typer.Exit(1)

        if res.status_code == 404:
            print_generic_message(
                f"No RemotiveTopology subscription found for account {account.email} and organization"
                + f"{valid_organization.display_name} (id: {valid_organization.uid})"
            )
            raise typer.Exit(0)

        subscription = Subscription.from_dict(res.json())

        # Determine if subscription is expired
        is_expired = subscription.end_date < datetime.datetime.now().date()
        status_text = "expired" if is_expired else "active"

        status_color = "red" if is_expired else "green"

        print_unformatted("RemotiveTopology subscription status")
        print_unformatted(f"  Account:      [bold]{account.email}[/bold]")
        print_unformatted(f"  Organization: [bold]{valid_organization.display_name}[/bold] (id: {valid_organization.uid})")
        print_unformatted(f"  Type:         [bold]{subscription.type}[/bold]")
        print_unformatted(f"  Status:       [bold {status_color}]{status_text}[/bold {status_color}]")
        print_unformatted(f"  Start date:   [bold]{subscription.start_date}[/bold]")
        print_unformatted(f"  End date:     [bold]{subscription.end_date}[/bold]")
    except NotSignedInError:
        print_generic_error(
            "You must first sign in to RemotiveCloud, please use [bold]remotive cloud auth login[/bold] to sign-in. "
            "This requires a RemotiveCloud account, if you do not have an account you can sign-up at https://cloud.remotivelabs.com"
        )
        raise typer.Exit(1)

    except NoActiveAccountError:
        print_hint(
            "You have not activated your account, please run [bold]remotive cloud auth activate[/bold] to choose an account "
            "or [bold]remotive cloud auth login[/bold] to sign-in"
        )
        raise typer.Exit(1)

    except NotAuthorizedError:
        print_hint(
            "Your current active credentials are not valid, please run [bold]remotive cloud auth login[/bold] to sign-in again. "
            "This requires a RemotiveCloud account, if you do not have an account you can sign-up at https://cloud.remotivelabs.com"
        )
        raise typer.Exit(1)

    except MissingOrganizationError:
        print_hint("You have not specified any organization and no default organization is set")
        print_unformatted("Run '[italic]remotive cloud organizations default[/italic]' to choose an organization")
        print_unformatted("Run '[italic]remotive cloud auth activate[/italic]' to change account if you have multiple accounts")
        raise typer.Exit(1)

    except NoOrganizationOrPermissionError as e:
        print_generic_error(f"Organization id {e.organization} does not exist or you do not have permission to access it.")
        raise typer.Exit(1)

    except typer.Exit:
        raise

    except Exception as e:
        print_generic_error(f"Unexpected error: {e}")
        raise typer.Exit(1)
