"""Performance analytics (scorekeeper / report card / benchmark) tests."""
from fastapi.testclient import TestClient

from app.main import app
from app.services.performance import _composite, _grade, MIN_TRADES_FOR_GRADE

client = TestClient(app)


def test_grades():
    assert _grade(85.0) == "A"
    assert _grade(72.0) == "B"
    assert _grade(63.0) == "C"
    assert _grade(51.0) == "D"
    assert _grade(20.0) == "F"
    assert _grade(None) == "—"


def test_composite_requires_min_trades():
    stats = {"trades": MIN_TRADES_FOR_GRADE - 1, "expectancy_r": 1.0, "win_rate": 80.0,
             "profit_factor": 2.0, "max_drawdown": 100.0, "total_pnl": 1000.0,
             "calibration_error": 5.0}
    assert _composite(stats) is None


def test_composite_rewards_better_stats():
    good = {"trades": 10, "expectancy_r": 0.8, "win_rate": 65.0, "profit_factor": 2.2,
            "max_drawdown": 200.0, "total_pnl": 3000.0, "calibration_error": 4.0}
    bad = {"trades": 10, "expectancy_r": -0.4, "win_rate": 30.0, "profit_factor": 0.6,
           "max_drawdown": 2000.0, "total_pnl": -1500.0, "calibration_error": 25.0}
    assert _composite(good) > _composite(bad)


def test_performance_endpoint_shape():
    client.post("/api/scanner/run")
    approved = client.get("/api/signals", params={"status": "approved"}).json()
    if approved:
        client.post("/api/paper-trades", json={"signal_id": approved[0]["id"]})
        trades = client.get("/api/paper-trades").json()
        open_ids = [t["id"] for t in trades if t["status"] == "open"]
        if open_ids:
            client.post(f"/api/paper-trades/{open_ids[0]}/close")

    r = client.get("/api/analytics/performance")
    assert r.status_code == 200
    body = r.json()
    assert "strategies" in body and "note" in body
    for s in body["strategies"]:
        assert s["strategy"] in ("options", "swing", "manual")
        assert s["grade"] in ("A", "B", "C", "D", "F", "—")


def test_benchmark_endpoint():
    r = client.get("/api/analytics/benchmark", params={"days": 30})
    assert r.status_code == 200
    body = r.json()
    assert body["period_days"] == 30
    assert "account_return_pct" in body and "spy_return_pct" in body


def test_mfe_mae_tracked_on_mark():
    client.post("/api/scanner/run")
    approved = client.get("/api/signals", params={"status": "approved"}).json()
    if not approved:
        return
    trade = client.post("/api/paper-trades", json={"signal_id": approved[0]["id"]}).json()
    client.post("/api/paper-trades/mark")
    trades = {t["id"]: t for t in client.get("/api/paper-trades").json()}
    t = trades.get(trade["id"])
    if t is not None:
        assert t["mfe_r"] >= 0 >= t["mae_r"]  # favorable ≥ 0 ≥ adverse by construction
