"""Unit tests for V38 live-conditioned projection (pure, no DB/model deps)."""

import os
import sys

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

from models.live_matrix import (
    build_live_projection,
    estimate_minute,
    state_multiplier,
)


def _approx(a, b, tol=1e-6):
    return abs(a - b) <= tol


def test_probs_form_distribution():
    proj = build_live_projection(0.50, 0.27, 0.23, 0.55, 1, 0, 60)
    p = proj["probs"]
    assert _approx(p["1"] + p["X"] + p["2"], 1.0, 1e-3)
    assert 0.0 <= proj["p_away_scores_again"] <= 1.0


def test_minute_one_roughly_matches_prematch():
    # at 0-0 minute 1 the projection must stay close to the anchored numbers
    proj = build_live_projection(0.50, 0.27, 0.23, 0.55, 0, 0, 1)
    assert abs(proj["probs"]["1"] - 0.50) < 0.06
    assert abs(proj["probs"]["2"] - 0.23) < 0.06


def test_one_goal_lead_at_80():
    # the user's exact case: 1-0 at 80' (OOS-validated: said 21.7 / actual 23.0)
    proj = build_live_projection(0.50, 0.27, 0.23, 0.55, 1, 0, 80)
    assert proj["probs"]["1"] > 0.72                 # leader is now strong fav
    assert 0.08 <= proj["p_away_scores_again"] <= 0.30
    assert _approx(
        proj["p_comeback"], proj["probs"]["X"] + proj["probs"]["2"], 1e-9
    )


def test_less_time_means_fewer_chances():
    early = build_live_projection(0.50, 0.27, 0.23, 0.55, 1, 0, 60)
    late = build_live_projection(0.50, 0.27, 0.23, 0.55, 1, 0, 85)
    assert late["p_away_scores_again"] < early["p_away_scores_again"]
    assert late["probs"]["1"] > early["probs"]["1"]


def test_trailing_team_pushes_late():
    assert state_multiplier(-1, 80) > 1.05    # trailing by one, late: pushes
    assert state_multiplier(1, 80) < 1.0      # leading by one, late: parks bus
    assert state_multiplier(-1, 80) > state_multiplier(-1, 30)


def test_score_consistency_with_current_score():
    proj = build_live_projection(0.50, 0.27, 0.23, 0.55, 2, 1, 75)
    # every scenario must be reachable from the current score
    for s in proj["scenario_top5"]:
        fh, fa = map(int, str(s["score"]).split("-"))
        assert fh >= 2 and fa >= 1
    assert proj["current_score"] == "2-1"


def test_estimate_minute_approximation():
    now = 1_700_000_000_000
    assert estimate_minute(None, now) is None
    assert estimate_minute(now + 60_000, now) is None          # not kicked off
    assert estimate_minute(now - 30 * 60_000, now) == 30        # mid 1H
    assert estimate_minute(now - 55 * 60_000, now) == 46        # HT break
    assert estimate_minute(now - 80 * 60_000, now) == 65        # 2H, break folded
    assert estimate_minute(now - 200 * 60_000, now) == 94       # capped


if __name__ == "__main__":
    fns = [v for k, v in sorted(globals().items()) if k.startswith("test_")]
    for fn in fns:
        fn()
        print(f"PASS {fn.__name__}")
    print(f"\nAll {len(fns)} tests passed.")
