# tests/test_pulse.py
from datetime import datetime, timezone, timedelta
import pulse

def _p(acc, mid, metric, days_ago):
    ts = (datetime.now(timezone.utc) - timedelta(days=days_ago)).isoformat()
    return {"post_id": f"tg:{acc}:{mid}", "account": acc, "metric": metric, "posted_at": ts}

def test_median():
    assert pulse.median([]) is None
    assert pulse.median([5]) == 5
    assert pulse.median([1, 3]) == 2
    assert pulse.median([1, 2, 3]) == 2

def test_hot_posts_flags_above_multiplier():
    now = datetime.now(timezone.utc)
    ws = now - timedelta(days=7)
    recs = [_p("a", 1, 100, 20), _p("a", 2, 100, 15), _p("a", 3, 100, 10),  # медиана ~100
            _p("a", 4, 250, 2),   # 2.5x медианы, в окне → HOT
            _p("a", 5, 120, 1)]   # 1.2x → не hot
    hot = pulse.hot_posts(recs, k=2.0, window_start=ws, now=now)
    ids = {h["post_id"] for h in hot}
    assert ids == {"tg:a:4"}
    assert hot[0]["ratio"] == 2.5

def test_hot_posts_ignores_out_of_window():
    now = datetime.now(timezone.utc)
    ws = now - timedelta(days=3)
    recs = [_p("a", 1, 100, 20), _p("a", 2, 100, 18), _p("a", 3, 300, 10)]  # 300 старое, вне окна
    assert pulse.hot_posts(recs, k=2.0, window_start=ws, now=now) == []

def test_hot_posts_ignores_none_metric_in_median():
    now = datetime.now(timezone.utc)
    ws = now - timedelta(days=7)
    # median over non-None metrics = median([100,100,100]) = 100; the None row is ignored
    recs = [_p("a", 1, 100, 5), _p("a", 2, 100, 4), _p("a", 3, 100, 3),
            _p("a", 4, None, 2),   # None metric — ignored in median, never flagged
            _p("a", 5, 250, 1)]    # 2.5x → HOT
    hot = pulse.hot_posts(recs, k=2.0, window_start=ws, now=now)
    ids = {h["post_id"] for h in hot}
    assert ids == {"tg:a:5"}
    assert all(h["post_id"] != "tg:a:4" for h in hot)

def test_hot_posts_skips_account_with_zero_or_none_median():
    now = datetime.now(timezone.utc)
    ws = now - timedelta(days=7)
    # account "z": all metrics None → median None → account skipped, no crash
    # account "y": all metrics 0 → median 0 → skipped (guard `if not med`)
    recs = [_p("z", 1, None, 3), _p("z", 2, None, 2),
            _p("y", 1, 0, 3), _p("y", 2, 0, 2)]
    assert pulse.hot_posts(recs, k=2.0, window_start=ws, now=now) == []
