"""Тесты для ЕКБ bbox-хелперов geocoder (#1871).

Покрывают:
- is_within_ekb_bbox_wide — ingest-guard (avito_detail координаты);
- is_within_ekb_bbox — geocoder tight-фильтр (поведение НЕ изменилось после DRY-рефактора);
- инвариант WIDE ⊇ TIGHT.
"""

import pytest

from app.services.geocoder import (
    EKB_BBOX_TIGHT,
    EKB_BBOX_WIDE,
    is_within_ekb_bbox,
    is_within_ekb_bbox_wide,
)

# Центр ЕКБ (Плотинка) — внутри обоих bbox.
EKB_CENTER = (56.838, 60.605)


@pytest.mark.parametrize(
    "lat,lon,expected",
    [
        (*EKB_CENTER, True),  # центр ЕКБ
        (56.797713, 60.609135, True),  # реальная EKB-карточка из avito-fixture
        (59.9386, 30.3141, False),  # Питер (#1871)
        (57.1530, 65.5343, False),  # Тюмень (#1871)
        (54.7388, 55.9721, False),  # Уфа (#1871)
        (57.0, 60.5, True),  # приграничье севернее tight, но в wide (В.Пышма зона)
    ],
)
def test_is_within_ekb_bbox_wide(lat: float, lon: float, expected: bool) -> None:
    assert is_within_ekb_bbox_wide(lat, lon) is expected


@pytest.mark.parametrize(
    "lat,lon",
    [
        (56.6, 60.3),  # юго-западный угол wide
        (57.1, 60.9),  # северо-восточный угол wide
        (56.6, 60.9),  # юго-восточный угол
        (57.1, 60.3),  # северо-западный угол
    ],
)
def test_wide_bbox_boundary_inclusive(lat: float, lon: float) -> None:
    """Границы wide-bbox включаются (inclusive)."""
    assert is_within_ekb_bbox_wide(lat, lon) is True


def test_wide_bbox_just_outside() -> None:
    """Чуть за границей wide-bbox → False."""
    assert is_within_ekb_bbox_wide(56.59, 60.605) is False  # южнее
    assert is_within_ekb_bbox_wide(57.11, 60.605) is False  # севернее
    assert is_within_ekb_bbox_wide(56.838, 60.29) is False  # западнее
    assert is_within_ekb_bbox_wide(56.838, 60.91) is False  # восточнее


def test_tight_bbox_behavior_unchanged() -> None:
    """geocoder tight-фильтр: те же числа, что и до DRY-рефактора (60.40-60.85 / 56.65-56.95)."""
    # внутри
    assert is_within_ekb_bbox(56.838, 60.605) is True
    # границы tight inclusive
    assert is_within_ekb_bbox(56.65, 60.40) is True
    assert is_within_ekb_bbox(56.95, 60.85) is True
    # чуть за tight → False (но в wide)
    assert is_within_ekb_bbox(56.64, 60.605) is False
    assert is_within_ekb_bbox(56.96, 60.605) is False
    assert is_within_ekb_bbox(56.838, 60.39) is False
    assert is_within_ekb_bbox(56.838, 60.86) is False


def test_wide_strictly_contains_tight() -> None:
    """Инвариант: всё, что прошло бы tight, проходит и wide.

    Гарантирует, что ingest-guard не режет ничего, что geocoder сам бы пропустил.
    """
    t_lat_min, t_lat_max, t_lon_min, t_lon_max = EKB_BBOX_TIGHT
    w_lat_min, w_lat_max, w_lon_min, w_lon_max = EKB_BBOX_WIDE
    assert w_lat_min <= t_lat_min
    assert w_lat_max >= t_lat_max
    assert w_lon_min <= t_lon_min
    assert w_lon_max >= t_lon_max
    # точечная проверка на углах tight
    for lat in (t_lat_min, t_lat_max):
        for lon in (t_lon_min, t_lon_max):
            assert is_within_ekb_bbox(lat, lon) is True
            assert is_within_ekb_bbox_wide(lat, lon) is True
