import shutil
import sys
from collections.abc import Iterable
from pathlib import Path

import nox
from nox.command import CommandFailed

nox.options.sessions = ["test"]


@nox.session
def test(session: nox.Session):
    session.env["MATURIN_PEP517_ARGS"] = "--profile=dev"
    session.install("-v", ".[dev]")

    def try_install_binary(package: str, constraint: str):
        try:
            session.install("--only-binary=:all:", f"{package}{constraint}")
        except CommandFailed:
            # No binary wheel available on this platform
            pass

    try_install_binary("numpy", ">=1.16")
    # https://github.com/zopefoundation/zope.interface/issues/316
    # - is a dependency of gevent
    try_install_binary("zope.interface", "<7")
    try_install_binary("gevent", ">=22.10.2")
    ignored_paths = []
    if sys.version_info < (3, 10):
        # Match syntax is only available in Python >= 3.10
        ignored_paths.append("tests/test_enums_match.py")
    ignore_args = [f"--ignore={path}" for path in ignored_paths]
    session.run("pytest", *ignore_args, *session.posargs)


@nox.session
def bench(session: nox.Session):
    session.install(".[dev]")
    session.run("pytest", "--benchmark-enable", "--benchmark-only", *session.posargs)


@nox.session
def mypy(session: nox.Session):
    type_checker(
        session,
        ("python", "-m", "mypy", "tests"),
    )
    # TODO: enable stubtest session.run_always("python", "-m", "mypy.stubtest", "pyo3_pytests")


@nox.session
def pyrefly(session: nox.Session):
    type_checker(
        session,
        ("python", "-m", "pyrefly", "check", "tests"),
    )


def type_checker(session: nox.Session, command: Iterable[str]):
    session.env["MATURIN_PEP517_ARGS"] = "--profile=dev"
    try:
        # We move the stubs where maturin is expecting them to be
        shutil.copytree("stubs", "pyo3_pytests")
        (Path("pyo3_pytests") / "py.typed").touch()
        session.install(".[dev]")

        session.run_always(*command)
    finally:
        shutil.rmtree("pyo3_pytests")
