"""Regression tests for app/api/v1/aggregation.py -- the dependency-free reduction step behind the
Part A2 company_summary() N+1 fix (docs/AUDIT_PERFORMANCE.md).

This is the ONLY part of the A2 fix that can run in this sandbox: everything else touched for A2
(security_eager_load_options(), is_demo_by_security(), and the screeners.py/rankings.py/
watchlist.py/companies.py call sites) needs a live sqlalchemy Session and a real Postgres database
to exercise -- sqlalchemy is not installed here (no network access to install it, confirmed
repeatedly across this overhaul, see docs/TEST_REPORT.md) -- so those pieces are DOCUMENTED / NOT
TESTED, verified only via `python3 -m py_compile`. See docs/AUDIT_PERFORMANCE_A2.md."""
from __future__ import annotations

from app.api.v1.aggregation import aggregate_is_demo_rows


def test_aggregate_is_demo_rows_all_real():
    rows = [("sec-1", False), ("sec-2", False)]
    assert aggregate_is_demo_rows(rows) == {"sec-1": False, "sec-2": False}


def test_aggregate_is_demo_rows_all_demo():
    rows = [("sec-1", True), ("sec-2", True)]
    assert aggregate_is_demo_rows(rows) == {"sec-1": True, "sec-2": True}


def test_aggregate_is_demo_rows_mixed_securities():
    rows = [("sec-1", True), ("sec-2", False)]
    assert aggregate_is_demo_rows(rows) == {"sec-1": True, "sec-2": False}


def test_aggregate_is_demo_rows_multiple_periods_same_security_any_true_wins():
    # a security with several FinancialPeriod rows -- realistic shape of the actual query result.
    # Even though this shouldn't happen in practice (one ingestion pipeline per security), the
    # aggregation must not silently pick an arbitrary one: ANY True makes the security demo.
    rows = [("sec-1", False), ("sec-1", False), ("sec-1", True)]
    assert aggregate_is_demo_rows(rows) == {"sec-1": True}


def test_aggregate_is_demo_rows_multiple_periods_same_security_all_false():
    rows = [("sec-1", False), ("sec-1", False)]
    assert aggregate_is_demo_rows(rows) == {"sec-1": False}


def test_aggregate_is_demo_rows_empty_input():
    assert aggregate_is_demo_rows([]) == {}


def test_aggregate_is_demo_rows_does_not_invent_securities_not_in_input():
    # a security with zero FinancialPeriod rows never appears in the query result at all --
    # is_demo_by_security()'s caller must use .get(security_id, False), not assume every requested
    # id comes back; this test documents that the aggregation itself makes no such guarantee.
    rows = [("sec-1", True)]
    result = aggregate_is_demo_rows(rows)
    assert "sec-2" not in result


ALL_TESTS = [obj for name, obj in list(globals().items()) if name.startswith("test_") and callable(obj)]

if __name__ == "__main__":
    passed, failed = 0, []
    for fn in ALL_TESTS:
        try:
            fn()
            passed += 1
            print(f"PASS  {fn.__name__}")
        except AssertionError as e:
            failed.append(fn.__name__)
            print(f"FAIL  {fn.__name__}: {e}")
    print(f"\n{passed}/{len(ALL_TESTS)} passed")
    if failed:
        raise SystemExit(1)
