"""Регулярные refresh-задачи для аналитического слоя.

Сейчас здесь:
- refresh_ekb_districts_median: пересчёт median/mean ₽/м² 8 районов ЕКБ из
  ДДУ-сделок rosreestr_deals (окно 24 мес).

Запускается через Celery beat (ежемесячно). См. workers/tasks/refresh_analytics.py.
"""

from __future__ import annotations

import logging
from typing import Any

from sqlalchemy import text
from sqlalchemy.orm import Session

logger = logging.getLogger(__name__)


def refresh_ekb_districts_median(
    db: Session,
    *,
    window_months: int = 24,
    min_deals: int = 50,
) -> list[dict[str, Any]]:
    """Пересчитать ekb_districts.median_price_per_m2 + mean_price_per_m2 из
    rosreestr ДДУ-сделок последних `window_months` месяцев.

    Использует SQL-функцию `refresh_ekb_districts_median(int, int)` из
    миграции 67_refresh_ekb_districts_median.sql. Возвращает список
    обновлённых районов с фактически использованными метриками.

    Не обновляет района с deals < min_deals (статистически шумно).
    Не трогает 'не определён' (служебная категория).
    """
    rows = (
        db.execute(
            text(
                """
                SELECT district_name, deals_used, median_pm, mean_pm
                  FROM refresh_ekb_districts_median(:wm, :md)
                """
            ),
            {"wm": window_months, "md": min_deals},
        )
        .mappings()
        .all()
    )
    db.commit()
    out = [
        {
            "district_name": r["district_name"],
            "deals_used": int(r["deals_used"]),
            "median_pm": float(r["median_pm"]) if r["median_pm"] is not None else None,
            "mean_pm": float(r["mean_pm"]) if r["mean_pm"] is not None else None,
        }
        for r in rows
    ]
    logger.info(
        "refresh_ekb_districts_median: window=%dmo min_deals=%d updated=%d districts",
        window_months,
        min_deals,
        len(out),
    )
    return out
