"""Tests para hotness_score."""

import math
from datetime import datetime, timedelta, timezone

from hotness_score import hotness_score

NOW = datetime(2024, 6, 1, 12, 0, 0, tzinfo=timezone.utc)


def test_active_count_zero_updated_at_reciente():
    """active_count=0, updated_at reciente."""
    updated_at = NOW - timedelta(hours=1)
    score = hotness_score(0, updated_at, now=NOW)
    # freq = sigmoid(log1p(0)) = sigmoid(0) = 0.5
    # recency ~ 1.0 (casi nuevo)
    assert 0.45 < score < 0.55, f"Expected ~0.5, got {score}"


def test_active_count_alto_updated_at_reciente():
    """active_count=100, updated_at reciente (score alto)."""
    updated_at = NOW - timedelta(hours=1)
    score = hotness_score(100, updated_at, now=NOW)
    # freq = sigmoid(log1p(100)) = sigmoid(4.615) ~ 0.99
    # recency ~ 1.0
    assert score > 0.95, f"Expected > 0.95, got {score}"


def test_active_count_alto_updated_at_hace_30_dias():
    """active_count=100, updated_at hace 30 dias (score bajo)."""
    updated_at = NOW - timedelta(days=30)
    score = hotness_score(100, updated_at, now=NOW)
    # recency = exp(-ln2/7 * 30) = exp(-2.97) ~ 0.051
    # score ~ 0.99 * 0.051 ~ 0.05
    assert score < 0.1, f"Expected < 0.1, got {score}"


def test_updated_at_none_retorna_cero():
    """updated_at=None (retorna 0.0)."""
    score = hotness_score(100, None, now=NOW)
    assert score == 0.0, f"Expected 0.0, got {score}"


def test_now_explicito():
    """now explicito (determinista para tests)."""
    updated_at = NOW - timedelta(days=7)
    score = hotness_score(50, updated_at, now=NOW)
    # recency = exp(-ln2/7 * 7) = 0.5
    # freq = sigmoid(log1p(50)) ~ sigmoid(3.93) ~ 0.981
    expected = (1.0 / (1.0 + math.exp(-math.log1p(50)))) * 0.5
    assert abs(score - expected) < 1e-9, f"Expected {expected}, got {score}"


def test_half_life_days_custom():
    """half_life_days custom."""
    updated_at = NOW - timedelta(days=1)
    # Con half_life=1 dia, despues de 1 dia recency = 0.5
    score = hotness_score(50, updated_at, now=NOW, half_life_days=1.0)
    freq = 1.0 / (1.0 + math.exp(-math.log1p(50)))
    expected = freq * 0.5
    assert abs(score - expected) < 1e-6, f"Expected {expected}, got {score}"
