from __future__ import annotations

import os
import traceback
import urllib.request
from typing import Any, Callable

import allure  # pyright: ignore[reportMissingImports]
from allure_commons.types import AttachmentType  # pyright: ignore[reportMissingImports]


def before_scenario(context: Any, scenario: Any) -> None:  # noqa: ARG001
    context._cleanup_fns = []  # type: ignore[attr-defined]

    # GraphQL endpoint выбирается в worklib.graphql_client.execute_graphql:
    # - явный аргумент graphql_url
    # - env GRAPHQL_URL
    # - DEFAULT_GRAPHQL_URL
    #
    # Для WireMock достаточно выставить USE_WIREMOCK=1.
    # Тогда тесты будут ходить в localhost:8080 и GraphQL, и Auth.
    if os.getenv("USE_WIREMOCK") in {"1", "true", "True"}:
        os.environ.setdefault("GRAPHQL_URL", "http://localhost:8080/graphql")
        os.environ.setdefault("AUTH_URL", "http://localhost:8080/api/v1/auth/login")

        # Важно: WireMock хранит состояние scenarioName между тестами.
        # Чтобы каждый behave-сценарий стартовал с "Started", сбрасываем сценарии и журнал запросов.
        try:
            for url in (
                "http://localhost:8080/__admin/reset",
                "http://localhost:8080/__admin/scenarios/reset",
                "http://localhost:8080/__admin/requests/reset",
            ):
                req = urllib.request.Request(url, data=b"", method="POST")
                urllib.request.urlopen(req, timeout=2).read()
        except Exception as e:  # noqa: BLE001
            # Не падаем, но прикладываем в Allure: иначе будет сложно понять 404 "Scenario does not match".
            allure.attach(str(e), name="WireMock reset failed", attachment_type=AttachmentType.TEXT)

    context.graphql_url = os.getenv("GRAPHQL_URL")


def after_scenario(context: Any, scenario: Any) -> None:  # noqa: ARG001
    cleanup_fns: list[Callable[[], None]] = getattr(context, "_cleanup_fns", [])
    while cleanup_fns:
        fn = cleanup_fns.pop()
        try:
            with allure.step(f"Cleanup: {getattr(fn, '__name__', 'cleanup')}"):
                fn()
        except Exception:
            allure.attach(
                traceback.format_exc(),
                name="Cleanup error",
                attachment_type=AttachmentType.TEXT,
            )

