"""Проверка, что backend-адаптеры структурно удовлетворяют scraper_kit.contracts.

Двойная проверка:
  1. Статическая — `_check_*` функции с аннотацией Protocol-типа. mypy проверит,
     что каждый адаптер присваивается соответствующему Protocol'у (структурно).
  2. Рантайм — `isinstance` против `@runtime_checkable` Protocol'ов (проверяет
     наличие методов/атрибутов). Ловит рассинхрон имён без запуска mypy.

Границы контрактов зафиксированы для #2131 (шаг B); переключение скрапперов на
инжекцию — шаг C.
"""

from __future__ import annotations

from scraper_kit.contracts import (
    EnrichmentJobs,
    HouseMatcher,
    ProxyProvider,
    ScraperConfig,
    SessionFactory,
)

from app.services.scraper_adapters import (
    RealEnrichmentJobs,
    RealMatcherAdapter,
    RealProxyProvider,
    RealScraperConfig,
    RealSessionFactory,
)


def _check_matcher(m: HouseMatcher) -> None:
    """Статическая проверка: RealMatcherAdapter ⊑ HouseMatcher."""


def _check_config(c: ScraperConfig) -> None:
    """Статическая проверка: RealScraperConfig ⊑ ScraperConfig."""


def _check_session_factory(f: SessionFactory) -> None:
    """Статическая проверка: RealSessionFactory ⊑ SessionFactory."""


def _check_enrichment(j: EnrichmentJobs) -> None:
    """Статическая проверка: RealEnrichmentJobs ⊑ EnrichmentJobs."""


def _check_proxy_provider(p: ProxyProvider) -> None:
    """Статическая проверка: RealProxyProvider ⊑ ProxyProvider."""


def test_matcher_adapter_satisfies_protocol() -> None:
    adapter = RealMatcherAdapter()
    _check_matcher(adapter)
    assert isinstance(adapter, HouseMatcher)
    assert callable(adapter.match_or_create_house)
    assert callable(adapter.upsert_listing_source)


def test_scraper_config_satisfies_protocol() -> None:
    config = RealScraperConfig()
    _check_config(config)
    assert isinstance(config, ScraperConfig)
    # Ключевые поля читаются без ошибок (проксируют в singleton settings).
    assert isinstance(config.scraper_fetch_mode, str)
    assert isinstance(config.browser_http_endpoint, str)
    assert isinstance(config.avito_proxy_max_rotations, int)
    assert isinstance(config.avito_serp_ekb_only, bool)
    # #2163: новый флаг proxy-пула присутствует и bool.
    assert isinstance(config.use_proxy_pool_curl, bool)
    # #2164 P4: флаг browser-пула присутствует и bool.
    assert isinstance(config.use_proxy_pool_browser, bool)


def test_proxy_provider_satisfies_protocol() -> None:
    provider = RealProxyProvider()
    _check_proxy_provider(provider)
    assert isinstance(provider, ProxyProvider)
    assert callable(provider.acquire)
    assert callable(provider.release)
    assert callable(provider.mark_health)


def test_session_factory_satisfies_protocol() -> None:
    factory = RealSessionFactory()
    _check_session_factory(factory)
    assert isinstance(factory, SessionFactory)


def test_enrichment_jobs_satisfies_protocol() -> None:
    jobs = RealEnrichmentJobs()
    _check_enrichment(jobs)
    assert isinstance(jobs, EnrichmentJobs)
    assert callable(jobs.house_imv_backfill)
    assert callable(jobs.house_dedup_merge)
    assert callable(jobs.yandex_address_backfill)


def test_contracts_module_has_no_app_imports() -> None:
    """contracts.py не должен импортировать app.* (иначе circular / coupling)."""
    import inspect

    import scraper_kit.contracts as contracts_mod

    source = inspect.getsource(contracts_mod)
    assert "from app" not in source
    assert "import app" not in source
