"""Тесты проброса browser-пула в SERP-скраперы yandex/cian (#2160).

Зеркало P4 (#2164) для avito: там пул раздавался только в avito-путях, а yandex/cian
SERP создавали BrowserFetcher сами в __aenter__ без пула → весь трафик шёл через
env-прокси браузера. Здесь проверяем, что YandexRealtyScraper / CianScraper прокидывают
proxy_provider + use_pool=config.use_proxy_pool_browser в BrowserFetcher.

Инвариант ship-dark:
  - proxy_provider=None ИЛИ флаг off → BrowserFetcher(..., proxy_provider=None, use_pool=False),
    т.е. env-прокси браузера, поведение байт-в-байт как до фикса.
  - proxy_provider задан + флаг on → BrowserFetcher получает провайдер + use_pool=True.

BrowserFetcher монки-патчится на recording-заглушку, так что реального HTTP к
tradein-browser не происходит.

После F4-миграции (#2362 F4b cian + #2363 F4c yandex) ОБА скрапера
(`yandex/serp.py::__aenter__` и `cian/serp.py::__aenter__`) больше не конструируют
`BrowserFetcher(...)` напрямую — оба вызывают shared `build_browser_fetcher()` из
`scraper_kit.providers._base`, который ВНУТРИ себя ссылается на СВОЙ собственный
импорт `BrowserFetcher`. Патч локального имени `yandex_serp.BrowserFetcher` /
`cian_serp.BrowserFetcher` больше не перехватывает вызов (реальный
`BrowserFetcher.__init__` конструировался бы, а `calls` оставался пуст) — поэтому
для обоих провайдеров патчим `scraper_kit.providers._base.BrowserFetcher`
(реальную зависимость `build_browser_fetcher`), сохраняя все assertions как есть.
Проверяемый инвариант (какие kwargs долетают до BrowserFetcher) не меняется —
меняется только точка патча, отражающая реальное место вызова.
"""

from __future__ import annotations

import types
from typing import Any

import pytest
from scraper_kit.providers import _base as kit_base
from scraper_kit.providers.cian import serp as cian_serp
from scraper_kit.providers.yandex import serp as yandex_serp


class _FakeProxyProvider:
    """ProxyProvider-заглушка: методы no-op (в этих тестах пул не вызывается —
    BrowserFetcher замокан, acquire/release не срабатывают)."""

    def acquire(self, provider: str) -> None:
        return None

    def release(self, lease: object) -> None:
        return None

    def mark_health(self, lease: object, ok: bool) -> None:
        return None


def _make_recorder() -> tuple[type, list[dict[str, Any]]]:
    """Recording-заглушка BrowserFetcher: пишет init-kwargs в общий список."""
    calls: list[dict[str, Any]] = []

    class _RecFetcher:
        def __init__(
            self,
            source: str = "avito",
            fetch_timeout_s: float = 120.0,
            *,
            endpoint: str,
            proxy_provider: object | None = None,
            use_pool: bool = False,
        ) -> None:
            calls.append(
                {
                    "source": source,
                    "endpoint": endpoint,
                    "proxy_provider": proxy_provider,
                    "use_pool": use_pool,
                }
            )

        async def __aenter__(self) -> _RecFetcher:
            return self

        async def __aexit__(self, *args: object) -> None:
            return None

    return _RecFetcher, calls


def _config(*, use_pool: bool) -> types.SimpleNamespace:
    return types.SimpleNamespace(
        browser_http_endpoint="http://browser:3000",
        use_proxy_pool_browser=use_pool,
    )


# ── Yandex SERP ──────────────────────────────────────────────────────────────


@pytest.mark.asyncio
async def test_yandex_serp_wires_pool_when_flag_on(monkeypatch: pytest.MonkeyPatch) -> None:
    """proxy_provider + флаг on → BrowserFetcher получает провайдер + use_pool=True."""
    rec_fetcher, calls = _make_recorder()
    monkeypatch.setattr("scraper_kit.providers._base.BrowserFetcher", rec_fetcher)
    provider = _FakeProxyProvider()

    scraper = yandex_serp.YandexRealtyScraper(_config(use_pool=True), proxy_provider=provider)
    async with scraper:
        pass

    assert len(calls) == 1
    assert calls[0]["source"] == "yandex"
    assert calls[0]["proxy_provider"] is provider
    assert calls[0]["use_pool"] is True


@pytest.mark.asyncio
async def test_yandex_serp_no_pool_by_default(monkeypatch: pytest.MonkeyPatch) -> None:
    """Без provider/флага → BrowserFetcher(proxy_provider=None, use_pool=False) — ship-dark."""
    rec_fetcher, calls = _make_recorder()
    monkeypatch.setattr("scraper_kit.providers._base.BrowserFetcher", rec_fetcher)

    scraper = yandex_serp.YandexRealtyScraper(_config(use_pool=False))
    async with scraper:
        pass

    assert len(calls) == 1
    assert calls[0]["proxy_provider"] is None
    assert calls[0]["use_pool"] is False


@pytest.mark.asyncio
async def test_yandex_serp_provider_without_flag_stays_dark(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    """provider задан, но флаг off → use_pool=False (BrowserFetcher пул не трогает)."""
    rec_fetcher, calls = _make_recorder()
    monkeypatch.setattr("scraper_kit.providers._base.BrowserFetcher", rec_fetcher)
    provider = _FakeProxyProvider()

    scraper = yandex_serp.YandexRealtyScraper(_config(use_pool=False), proxy_provider=provider)
    async with scraper:
        pass

    assert calls[0]["proxy_provider"] is provider
    assert calls[0]["use_pool"] is False


# ── Cian SERP ────────────────────────────────────────────────────────────────


@pytest.mark.asyncio
async def test_cian_serp_wires_pool_when_flag_on(monkeypatch: pytest.MonkeyPatch) -> None:
    """proxy_provider + флаг on → BrowserFetcher получает провайдер + use_pool=True."""
    rec_fetcher, calls = _make_recorder()
    # #2362: CianScraper.__aenter__ теперь строит BrowserFetcher через
    # _base.build_browser_fetcher() — патчим класс там, не в cian_serp.
    monkeypatch.setattr(kit_base, "BrowserFetcher", rec_fetcher)
    provider = _FakeProxyProvider()

    scraper = cian_serp.CianScraper(_config(use_pool=True), proxy_provider=provider)
    async with scraper:
        pass

    assert len(calls) == 1
    assert calls[0]["source"] == "cian"
    assert calls[0]["proxy_provider"] is provider
    assert calls[0]["use_pool"] is True


@pytest.mark.asyncio
async def test_cian_serp_no_pool_by_default(monkeypatch: pytest.MonkeyPatch) -> None:
    """Без provider/флага → BrowserFetcher(proxy_provider=None, use_pool=False) — ship-dark."""
    rec_fetcher, calls = _make_recorder()
    monkeypatch.setattr(kit_base, "BrowserFetcher", rec_fetcher)

    scraper = cian_serp.CianScraper(_config(use_pool=False))
    async with scraper:
        pass

    assert len(calls) == 1
    assert calls[0]["proxy_provider"] is None
    assert calls[0]["use_pool"] is False
