import sys

import click

from great_expectations import DataContext
from great_expectations import exceptions as gx_exceptions
from great_expectations.cli.v012.cli_messages import SECTION_SEPARATOR
from great_expectations.cli.v012.toolkit import load_data_context_with_error_handling
from great_expectations.cli.v012.util import cli_message
from great_expectations.core.usage_statistics.util import send_usage_message
from great_expectations.data_context.types.base import CURRENT_GX_CONFIG_VERSION


@click.group()
def project() -> None:
    """Project operations"""
    pass


@project.command(name="check-config")
@click.option(
    "--directory",
    "-d",
    default="./great_expectations",
    help="The project's great_expectations directory.",
)
def project_check_config(directory) -> None:
    """Check a config for validity and help with migrations."""
    cli_message("Checking your config files for validity...\n")
    is_config_ok, error_message, context = do_config_check(directory)
    if context:
        send_usage_message(
            data_context=context,
            event="cli.project.check_config",
            api_version="v2",
            success=True,
        )
    if not is_config_ok:
        cli_message("Unfortunately, your config appears to be invalid:\n")
        cli_message(f"<red>{error_message}</red>")
        sys.exit(1)

    cli_message("<green>Your config file appears valid!</green>")


@project.command(name="upgrade")
@click.option(
    "--directory",
    "-d",
    default="./great_expectations",
    help="The project's great_expectations directory.",
)
def project_upgrade(directory) -> None:
    """Upgrade a project after installing the next Great Expectations major version."""
    cli_message("\nChecking project...")
    cli_message(SECTION_SEPARATOR)
    if load_data_context_with_error_handling(
        directory=directory, from_cli_upgrade_command=True
    ):
        up_to_date_message = (
            "Your project is up-to-date - no further upgrade is necessary.\n"
        )
        cli_message(f"<green>{up_to_date_message}</green>")
        sys.exit(0)


def do_config_check(target_directory):
    try:
        context = DataContext(context_root_dir=target_directory)
        ge_config_version: int = context.get_config().config_version
        if int(ge_config_version) < CURRENT_GX_CONFIG_VERSION:
            upgrade_message: str = f"""The config_version of your great_expectations.yml -- {float(ge_config_version)} -- is outdated.
Please consult the V3 API migration guide https://docs.greatexpectations.io/en/latest/guides/how_to_guides/migrating_versions.html and
upgrade your Great Expectations configuration to version {float(CURRENT_GX_CONFIG_VERSION)} in order to take advantage of the latest capabilities.
            """
            return (
                False,
                upgrade_message,
                None,
            )
        return True, None, context
    except (
        gx_exceptions.InvalidConfigurationYamlError,
        gx_exceptions.InvalidTopLevelConfigKeyError,
        gx_exceptions.MissingTopLevelConfigKeyError,
        gx_exceptions.InvalidConfigValueTypeError,
        gx_exceptions.UnsupportedConfigVersionError,
        gx_exceptions.DataContextError,
        gx_exceptions.PluginClassNotFoundError,
        gx_exceptions.PluginModuleNotFoundError,
        gx_exceptions.GreatExpectationsError,
    ) as err:
        return False, err.message, None
