"""Platform Expansion v2: news intelligence + crypto engine tests."""
from fastapi.testclient import TestClient

from app.agents.news import NewsAgent
from app.main import app
from app.services.market_data import MockMarketDataProvider, is_crypto
from app.services.news import MockNewsProvider, heuristic_news_score

client = TestClient(app)
provider = MockMarketDataProvider()


# ── News intelligence ──────────────────────────────────────
def test_mock_news_deterministic():
    a = MockNewsProvider().get_news("TSLA")
    b = MockNewsProvider().get_news("TSLA")
    assert a == b and len(a) > 0
    assert all(h["headline"] for h in a)


def test_heuristic_scoring_direction():
    positive = [{"headline": "Company beats estimates and raises guidance", "summary": ""}]
    negative = [{"headline": "Company faces SEC investigation and lawsuit", "summary": ""}]
    neutral = [{"headline": "Company schedules investor day", "summary": ""}]
    assert heuristic_news_score(positive)["score"] > 50
    assert heuristic_news_score(negative)["score"] < 50
    assert heuristic_news_score(neutral)["score"] == 50
    assert heuristic_news_score(negative)["negative_catalysts"]


def test_news_agent_bounds_and_disable(monkeypatch):
    ctx = {"symbol": "TSLA", "history": provider.get_history("TSLA", 90),
           "quote": provider.get_quote("TSLA")}
    result = NewsAgent().run(ctx)
    assert 0 <= result.score <= 100
    assert result.data["method"] in ("heuristic", "llm")

    monkeypatch.setenv("NEWS_ENABLED", "false")
    disabled = NewsAgent().run(ctx)
    assert disabled.score == 50.0 and disabled.data["method"] == "disabled"


def test_news_flows_into_signals():
    client.post("/api/scanner/run")
    signals = client.get("/api/signals").json()
    with_news = [s for s in signals if s["signal_type"] == "options" and "news" in s["scores"]]
    assert with_news, "options signals should carry a news score"
    for s in with_news[:3]:
        assert 0 <= s["scores"]["news"] <= 100


# ── Crypto engine ──────────────────────────────────────────
def test_is_crypto():
    assert is_crypto("BTC/USD") and not is_crypto("TSLA")


def test_mock_crypto_history_247():
    bars = provider.get_history("BTC/USD", 90)
    assert len(bars) == 90  # crypto trades every day — no weekend gaps
    assert all(b["close"] > 0 for b in bars)
    quote = provider.get_quote("BTC/USD")
    assert quote["price"] > 0


def test_crypto_disabled_by_default():
    client.post("/api/scanner/run")
    signals = client.get("/api/signals").json()
    assert not any(s["signal_type"] == "crypto" for s in signals)


def test_crypto_pipeline_when_enabled(monkeypatch):
    monkeypatch.setenv("CRYPTO_ENABLED", "true")
    r = client.post("/api/scanner/run")
    assert r.status_code == 200
    signals = client.get("/api/signals").json()
    crypto = [s for s in signals if s["signal_type"] == "crypto"]
    # Mock random-walks may or may not qualify — but any created must be valid
    for s in crypto:
        assert s["direction"] in ("BUY", "SELL")
        assert s["option_contract"] == {}
        assert "/" in s["symbol"]
        assert s["status"] in ("approved", "rejected")
