import argparse
from argparse import (
    ArgumentParser,
    Namespace,
)
from inspect import cleandoc
from pathlib import Path

import nox
from nox import Session

from exasol.toolbox.util.version import Version
from noxconfig import (
    PROJECT_CONFIG,
    Config,
)

_SUCCESS = 0
_FAILURE = 1

# fmt: off
_VERSION_MODULE_TEMPLATE = cleandoc('''
    """
    ATTENTION:
        This file is generated by exasol/toolbox/nox/_package_version.py when using:
            * either "poetry run -- nox -s project:fix"
            * or "poetry run -- nox -s version:check -- --fix"
    Do not edit this file manually!
    If you need to change the version, do so in the pyproject.toml, e.g. by using
    `poetry version X.Y.Z`.
    """

    MAJOR = {major}
    MINOR = {minor}
    PATCH = {patch}
    VERSION = f"{{MAJOR}}.{{MINOR}}.{{PATCH}}"
    __version__ = VERSION
''') + "\n"
# fmt: on


def write_version_module(version: Version, version_file: Path) -> None:
    with version_file.open(mode="w", encoding="utf-8") as f:
        f.write(
            _VERSION_MODULE_TEMPLATE.format(
                major=version.major, minor=version.minor, patch=version.patch
            )
        )


def _create_parser() -> ArgumentParser:
    parser = ArgumentParser(
        prog="nox -s version:check --",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    )
    parser.add_argument(
        "-d",
        "--debug",
        action="store_true",
        default=False,
        help="enabled debug mode for execution.",
    )
    parser.add_argument(
        "-f",
        "--fix",
        action="store_true",
        default=False,
        help="updates the `version.py`, instead of performing a check.",
    )
    return parser


def _version_check(args: Namespace, config: Config) -> int:
    version_file = config.version_file

    module_version = Version.from_python_module(version_file)
    poetry_version = Version.from_poetry()
    if args.fix:
        print(
            f"Updating version in {version_file} from {module_version} to {poetry_version}"
        )
        write_version_module(version=poetry_version, version_file=version_file)
        module_version = Version.from_python_module(version_file)

    if module_version != poetry_version:
        print(
            f"Version in pyproject.toml ({poetry_version}) and {version_file} ({module_version}) do not match!"
        )
        return _FAILURE

    return _SUCCESS


@nox.session(name="version:check", python=False)
def version_check(session: Session) -> None:
    """
    Compare the version in the `version.py` to that
    declared in the `pyproject.toml`.
    """
    parser = _create_parser()
    args = parser.parse_args(session.posargs)
    if _version_check(args=args, config=PROJECT_CONFIG):
        session.error()
