"""The package entry point."""

from __future__ import annotations

import argparse
import functools
import os
import pathlib
import platform
import shutil
import subprocess
import sys
from typing import TYPE_CHECKING, NamedTuple

import venver

if TYPE_CHECKING:
    from collections.abc import Callable


@functools.lru_cache(1)
def _ensure_supported_platform() -> None:
    system = platform.system()
    if system != "Linux":
        msg = f"unsupported system: {system}"
        raise RuntimeError(msg)


@functools.lru_cache(1)
def _bin() -> pathlib.Path:
    _ensure_supported_platform()
    return (
        (pathlib.Path.home() / ".local" / "share" / venver.__distribution__ / ".venv" / "bin")
        .expanduser()
        .resolve()
    )


@functools.lru_cache(1)
def _local_bin() -> pathlib.Path:
    _ensure_supported_platform()
    return (pathlib.Path.home() / ".local" / "bin").expanduser().resolve()


_BASH_PATH = """\
\033[34mAdd this to your `.bashrc`\
\033[1;0m\

export PATH="%s:${PATH}"\
\033[0m\
"""
_BASH_ENABLE = """\
\033[34mMake sure this is in your `.bashrc`.\
\033[1;0m\

_venver() {
   eval "$(venver-command)"
}
PROMPT_COMMAND="_venver;${PROMPT_COMMAND}"\
\033[0m\
"""
_MANAGE = """\
\033[34mManage venver\
\033[1;0m\

venver -h      # show the help message
venver bash    # show the instructions to configure the bash shell
venver update  # update venver to the latest available version\
\033[0m\
"""


class Args(NamedTuple):
    """Command line arguments."""

    command: Callable[[], int]


def _bash() -> int:
    _ensure_supported_platform()
    path = os.getenv("PATH", "")
    if not next(
        filter(lambda p: pathlib.Path(p).expanduser().resolve() == _local_bin(), path.split(":")),
        False,
    ):
        print(_BASH_PATH % _local_bin(), end="\n\n")  # noqa: T201
    print(_BASH_ENABLE)  # noqa: T201
    return 0


def _update() -> int:
    _ensure_supported_platform()
    pip = shutil.which("pip3")
    if not pip:
        print(  # noqa: T201
            f"Failed to update {venver.__distribution__} because `pip` was not found",
            file=sys.stderr,
        )
        return 1
    args = [
        pip,
        "--python",
        str(_bin() / "python3"),
        "install",
        venver.__distribution__,
        "--upgrade",
    ]
    res = subprocess.run(args, check=False)  # noqa: S603
    return res.returncode


def _manage() -> int:
    print(_MANAGE)  # noqa: T201
    return 0


def cli(*, argv: list[str] | None = None, namespace: argparse.Namespace | None = None) -> int:
    """The entry point function."""
    parser = argparse.ArgumentParser(prog="venver", description="Manage venver.")
    parser.add_argument(
        "-v",
        "--version",
        action="version",
        version=f"{venver.__distribution__} {venver.__version__}",
    )
    subparsers = parser.add_subparsers(title="commands")
    parser_bash = subparsers.add_parser("bash", help="configure bash")
    parser_bash.set_defaults(command=_bash)
    parser_update = subparsers.add_parser("update", help="update venver")
    parser_update.set_defaults(command=_update)
    parser_manage = subparsers.add_parser("manage", help="example usage")
    parser_manage.set_defaults(command=_manage)
    try:
        args = Args(**parser.parse_args(argv, namespace).__dict__)
    except TypeError:
        parser.print_help(sys.stderr)
        return 1
    else:
        return args.command()


if __name__ == "__main__":
    raise SystemExit(cli())
