# flake8: noqa: E501

import subprocess

from pathlib import Path
from typing import List, Tuple

import pytest


CURRENT_DIR = Path(__file__).parent


def run_check(path_location: str) -> str:
    """Use mypy to check the given path location and return the output."""

    mypy_path = "mypy"
    path = CURRENT_DIR / path_location
    command = [mypy_path, path.resolve().as_posix()]

    process = subprocess.run(
        command,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        universal_newlines=True,
    )
    output = process.stdout + process.stderr
    return output


@pytest.mark.parametrize(
    "path_location,expected",
    (
        (
            "app_default.py",
            [
                (
                    "sanic.app.Sanic[sanic.config.Config, types.SimpleNamespace]",
                    5,
                )
            ],
        ),
        (
            "app_custom_config.py",
            [
                (
                    "sanic.app.Sanic[app_custom_config.CustomConfig, types.SimpleNamespace]",
                    10,
                )
            ],
        ),
        (
            "app_custom_ctx.py",
            [("sanic.app.Sanic[sanic.config.Config, app_custom_ctx.Foo]", 9)],
        ),
        (
            "app_fully_custom.py",
            [
                (
                    "sanic.app.Sanic[app_fully_custom.CustomConfig, app_fully_custom.Foo]",
                    14,
                )
            ],
        ),
        (
            "request_custom_sanic.py",
            [
                ("types.SimpleNamespace", 18),
                (
                    "sanic.app.Sanic[request_custom_sanic.CustomConfig, types.SimpleNamespace]",
                    19,
                ),
            ],
        ),
        (
            "request_custom_ctx.py",
            [
                ("request_custom_ctx.Foo", 16),
                (
                    "sanic.app.Sanic[sanic.config.Config, types.SimpleNamespace]",
                    17,
                ),
            ],
        ),
        (
            "request_fully_custom.py",
            [
                ("request_fully_custom.CustomRequest", 32),
                ("request_fully_custom.RequestContext", 33),
                (
                    "sanic.app.Sanic[request_fully_custom.CustomConfig, request_fully_custom.Foo]",
                    34,
                ),
            ],
        ),
    ),
)
def test_check_app_default(
    path_location: str, expected: List[Tuple[str, int]]
) -> None:
    output = run_check(f"samples/{path_location}")

    for text, number in expected:
        current = CURRENT_DIR / f"samples/{path_location}"
        path = current.relative_to(CURRENT_DIR.parent)

        target = Path.cwd()
        while True:
            note = _text_from_path(current, path, target, number, text)
            try:
                assert note in output, output
            except AssertionError:
                target = target.parent
                if not target.exists() or target == target.parent:
                    raise
            else:
                break


def _text_from_path(
    base: Path, path: Path, target: Path, number: int, text: str
) -> str:
    relative_to_cwd = base.relative_to(target)
    prefix = ".".join(relative_to_cwd.parts[:-1])
    text = text.replace(path.stem, f"{prefix}.{path.stem}")
    return f'{path}:{number}: note: Revealed type is "{text}"'
