"""#1789 — rating_score из reviews.filterEntries[type==score] (fallback).

Avito перенёс сводный рейтинг из housePage.developmentData.ratingPreview в виджет
reviews.filterEntries[{type: 'score', value: {scoreFloat, scoreString, reviewCount, ratingStat}}].

Тест 1: когда housePage НЕ даёт рейтинг (ratingBadge пуст), rating берётся из
        reviews.filterEntries — проверяем rating_score/rating_string/reviews_count/
        rating_distribution.

Тест 2: housePage даёт рейтинг (старый путь ratingBadge) → filterEntries НЕ
        перезаписывает (приоритет housePage).

Тест 3: новостройка (developmentPage) без reviews-виджета → graceful, нет краша.

Без сети, без БД.
"""

from __future__ import annotations

import os

import pytest

os.environ.setdefault("DATABASE_URL", "postgresql+psycopg://test:test@localhost/test_db")

from app.services.scrapers.avito_houses import parse_houses_state


def _make_state(
    *,
    house_page_rating: dict | None = None,
    reviews_filter_entries: list | None = None,
) -> dict:
    """Минимальный __preloadedState__ с housePage и опциональными reviews.

    house_page_rating — если задан, проставляем в developmentData (старый путь).
    reviews_filter_entries — если задан, проставляем в reviews.props.reviews.filterEntries
    """
    dev_data: dict = {
        "avitoId": 555666,
        "id": "aGFzaA==",
        "title": "Test House",
        "address": "ул. Тестовая, 1",
        "coords": {"lat": 56.8, "lng": 60.6},
        "aboutDevelopment": {"expandParams": {"items": []}},
        "developer": {},
        "mapPreview": {},
    }
    if house_page_rating is not None:
        dev_data.update(house_page_rating)

    placeholders: list = [
        {
            "type": "housePage",
            "props": {"developmentData": dev_data},
        },
    ]

    if reviews_filter_entries is not None:
        placeholders.append(
            {
                "type": "reviews",
                "props": {
                    # MFE-форма: данные под ключом "reviews" внутри props
                    "reviews": {
                        "entries": [],
                        "filterEntries": reviews_filter_entries,
                    }
                },
            }
        )

    return {"data": {"data": {"page": {"placeholders": placeholders}}}}


# ---------------------------------------------------------------------------
# Тест 1: рейтинг из reviews.filterEntries (housePage пуст)
# ---------------------------------------------------------------------------


def test_rating_from_filter_entries_when_housepage_empty() -> None:
    """Когда housePage не даёт рейтинг — берём из reviews.filterEntries."""
    state = _make_state(
        reviews_filter_entries=[
            {
                "type": "score",
                "value": {
                    "scoreFloat": 4.666,
                    "scoreString": "4,7",
                    "reviewCount": 3,
                    "ratingStat": [
                        {"score": 5, "count": 2},
                        {"score": 4, "count": 1},
                    ],
                },
            }
        ]
    )

    e = parse_houses_state(state, "/catalog/houses/ekaterinburg/test/555666")
    h = e.house

    assert h.rating_score == pytest.approx(4.666, rel=1e-3)
    assert h.rating_string == "4,7"
    assert h.reviews_count == 3
    assert len(h.rating_distribution) == 2
    assert h.rating_distribution[0]["score"] == 5


def test_rating_filter_entries_float_type() -> None:
    """scoreFloat из filterEntries конвертируется в float (не остаётся int/str)."""
    state = _make_state(
        reviews_filter_entries=[
            {
                "type": "score",
                "value": {"scoreFloat": 5, "scoreString": "5,0", "reviewCount": 1},
            }
        ]
    )
    e = parse_houses_state(state, "/catalog/houses/ekaterinburg/test/555666")
    assert isinstance(e.house.rating_score, float)
    assert e.house.rating_score == 5.0


# ---------------------------------------------------------------------------
# Тест 2: housePage даёт рейтинг → filterEntries НЕ перезаписывает
# ---------------------------------------------------------------------------


def test_housepage_rating_takes_priority_over_filter_entries() -> None:
    """Если housePage.ratingBadge уже заполнен — filterEntries не перезаписывает."""
    state = _make_state(
        house_page_rating={
            "ratingBadge": {"info": {"score": 3.9, "scoreString": "3,9"}},
            "ratingSummaryStat": {"reviewCount": 10, "ratingStat": []},
        },
        reviews_filter_entries=[
            {
                "type": "score",
                "value": {
                    "scoreFloat": 4.9,
                    "scoreString": "4,9",
                    "reviewCount": 99,
                    "ratingStat": [],
                },
            }
        ],
    )

    e = parse_houses_state(state, "/catalog/houses/ekaterinburg/test/555666")
    h = e.house

    # Значение из housePage должно сохраниться
    assert h.rating_score == pytest.approx(3.9, rel=1e-3)
    assert h.rating_string == "3,9"
    assert h.reviews_count == 10


# ---------------------------------------------------------------------------
# Тест 3: нет reviews-виджета вообще → None, не падаем
# ---------------------------------------------------------------------------


def test_no_reviews_widget_rating_is_none() -> None:
    """Без виджета reviews и без ratingBadge → rating_score=None, graceful."""
    state = _make_state()  # нет reviews_filter_entries

    e = parse_houses_state(state, "/catalog/houses/ekaterinburg/test/555666")
    h = e.house

    assert h.rating_score is None
    assert h.rating_string is None
    assert h.reviews_count is None


# ---------------------------------------------------------------------------
# Тест 4: filterEntries без entry type==score → rating остаётся None
# ---------------------------------------------------------------------------


def test_filter_entries_without_score_type() -> None:
    """filterEntries без type==score → рейтинг не заполняется."""
    state = _make_state(
        reviews_filter_entries=[
            {"type": "something_else", "value": {"scoreFloat": 9.9}},
        ]
    )
    e = parse_houses_state(state, "/catalog/houses/ekaterinburg/test/555666")
    assert e.house.rating_score is None
