# pulse.py
"""Скоринг «залетело» по медиане метрики внутри одного прогона (без истории)."""
from datetime import datetime
from typing import List, Optional


def median(values) -> Optional[float]:
    vals = sorted(v for v in values if v is not None)
    if not vals:
        return None
    n = len(vals)
    mid = n // 2
    if n % 2:
        return float(vals[mid])
    return (vals[mid - 1] + vals[mid]) / 2.0


def _parse_ts(value: str) -> datetime:
    value = value.replace("Z", "+00:00")
    if value.endswith("+0000"):
        value = value[:-5] + "+00:00"
    return datetime.fromisoformat(value)


def hot_posts(records: List[dict], k: float, window_start: datetime,
              now: datetime) -> List[dict]:
    """Для источника со «своей лентой» (ТГ): пост залетел, если его метрика
    >= k * медианы канала. Медиана — по всем отданным постам аккаунта."""
    by_acc = {}
    for r in records:
        by_acc.setdefault(r["account"], []).append(r)
    hot = []
    for acc, recs in by_acc.items():
        med = median([r.get("metric") for r in recs])
        if not med:
            continue
        for r in recs:
            m = r.get("metric")
            if m is None:
                continue
            ts = _parse_ts(r["posted_at"])
            if not (window_start <= ts <= now):
                continue
            ratio = m / med
            if ratio >= k:
                hot.append({**r, "ratio": round(ratio, 2)})
    hot.sort(key=lambda r: r["ratio"], reverse=True)
    return hot
