import os
import platform
import subprocess
import sys
import webbrowser
from pathlib import Path


def get_project_root():
    return Path(__file__).parent.resolve()


def bootstrap():
    """
    Called when first non-standard lib import fails.

    We need to install the development requirements to use this script.
    """

    def get_base_prefix_compat():
        """Get base/real prefix, or sys.prefix if there is none."""
        return getattr(sys, "base_prefix", None) or getattr(sys, "real_prefix", None) or sys.prefix

    def in_virtualenv():
        return get_base_prefix_compat() != sys.prefix

    def pip_install(package):
        subprocess.run([sys.executable, "-m", "pip", "install", package], check=True)

    if not in_virtualenv():
        print("Please create a virtual environment first and activate it!")
        sys.exit(1)

    pip_install("flit")

    print("Empty virtualenv, installing development dependencies..")
    subprocess.run([sys.executable, "-m", "flit", "install", "-s"], check=True)


try:
    import typer
except ImportError:
    bootstrap()
    import typer

from rich import print  # noqa

cli = typer.Typer()


def get_pythonpath():
    """Add project root and model directory to string"""
    project_root = str(get_project_root())
    model_root = str(Path(__file__).parent / "model")
    return f"{project_root}:{model_root}"


def env_with_pythonpath():
    """Get en environment dict with includes PYTHONPATH"""
    env = os.environ.copy()
    env["PYTHONPATH"] = get_pythonpath()
    return env


@cli.command()
def mypy():
    """Run Mypy (configured in pyproject.toml)"""
    subprocess.run(["mypy", "cast"])


@cli.command()
def test(test_path: str = typer.Argument(None)):
    if test_path is None:
        test_path = "tests"
    subprocess.call([sys.executable, "runtests.py", test_path])
    # FIXME use pytest after fixing removing test images after running tests
    # subprocess.call(["python", "-m", "pytest"], env=env_with_pythonpath())


@cli.command()
def coverage():
    """
    Run and show coverage.
    """
    subprocess.call(["coverage", "run", "-m", "pytest"], env=env_with_pythonpath())
    subprocess.call(["coverage", "html"])
    if platform.system() == "Darwin":
        subprocess.call(["open", "htmlcov/index.html"])
    elif platform.system() == "Linux" and "Microsoft" in platform.release():  # on WSL
        subprocess.call(["explorer.exe", r"htmlcov\index.html"])


@cli.command()
def jupyterlab():
    """
    Start a jupyterlab server.
    """
    project_root = get_project_root()
    notebook_dir = project_root / "notebooks"
    notebook_dir.mkdir(exist_ok=True)
    env = env_with_pythonpath() | {"DJANGO_ALLOW_ASYNC_UNSAFE": "true"}
    subprocess.call([sys.executable, "example/manage.py", "shell_plus", "--notebook"], env=env)


@cli.command()
def docs():
    autogenerated = [
        "cast.api.rst",
        "cast.migrations.rst",
        "cast.rst",
        "cast.templatetags.rst",
        "modules.rst",
    ]
    for rst_name in autogenerated:
        (Path("docs") / rst_name).unlink(missing_ok=True)
    commands = [
        # ["sphinx-apidoc", "-o", "docs/", "cast"],
        ["make", "-C", "docs", "clean"],
        ["make", "-C", "docs", "html"],
    ]
    for command in commands:
        subprocess.call(command)
    file_url = "file://" + str(Path("docs/_build/html/index.html").resolve())
    webbrowser.open_new_tab(file_url)


if __name__ == "__main__":
    cli()
