"""app.utils.meituan_city.get_meituan_city 经纬度→美团城市 反查测试。

覆盖 get_meituan_city 的分支(test_geo.py 只覆盖底层 get_city):
  - 主要城市 → 正确省份 + 非空 city_id(+ 直辖市/省会命中中文城市名)
  - 非中国境内坐标 → city_id 为空(接口据此降级返空)
  - 返回 dict 结构 / 类型
  - 坐标量化(~1km)后近点命中同一缓存结果
  - 返回的是缓存副本(调用方原地修改不污染缓存)
"""
from __future__ import annotations

import pytest

from app.utils.meituan_city import get_meituan_city

# (标签, 纬度, 经度, 期望省份名, 期望城市名)
_CASES = [
    ("北京", 39.9042, 116.4074, "北京市", "北京市"),
    ("上海", 31.2304, 121.4737, "上海市", "上海市"),
    ("广州", 23.1291, 113.2644, "广东省", "广州市"),
    ("深圳", 22.5431, 114.0579, "广东省", "深圳市"),
    ("成都", 30.5728, 104.0668, "四川省", "成都市"),
    ("杭州", 30.2741, 120.1551, "浙江省", "杭州市"),
    ("武汉", 30.5928, 114.3055, "湖北省", "武汉市"),
    ("郑州", 34.7466, 113.6253, "河南省", "郑州市"),
    ("厦门", 24.4798, 118.0894, "福建省", "厦门市"),
    ("青岛", 36.0671, 120.3826, "山东省", "青岛市"),
]


@pytest.mark.parametrize("label,lat,lon,exp_province,exp_city", _CASES)
def test_major_city_resolves(label: str, lat: float, lon: float,
                             exp_province: str, exp_city: str) -> None:
    r = get_meituan_city(lat, lon)
    assert r["province_name"] == exp_province, f"{label}: province {r!r}"
    assert r["city_name"] == exp_city, f"{label}: city {r!r}"
    assert r["city_id"], f"{label}: city_id 不应为空 {r!r}"


def test_non_china_returns_empty_city_id() -> None:
    """境外/远洋坐标 → city_id 空(接口据此返回 degraded 空列表)。"""
    r = get_meituan_city(0.0, -140.0)   # 太平洋中部
    assert r["city_id"] == "", f"境外不应给出 city_id: {r!r}"


def test_return_shape_and_types() -> None:
    r = get_meituan_city(39.9042, 116.4074)
    for key in ("city_id", "city_name", "province_name"):
        assert key in r and isinstance(r[key], str)


def test_quantized_coords_hit_same_result() -> None:
    """相距 <1km(round 到 2 位小数后相同)的两点应解析出同一城市。"""
    a = get_meituan_city(39.9042, 116.4074)
    b = get_meituan_city(39.9031, 116.4066)   # round 后同为 (39.90, 116.41)
    assert a == b


def test_result_is_defensive_copy() -> None:
    """返回的是缓存副本:原地修改不应污染后续查询。"""
    first = get_meituan_city(31.2304, 121.4737)
    first["city_id"] = "TAMPERED"
    second = get_meituan_city(31.2304, 121.4737)
    assert second["city_id"] != "TAMPERED"
