"""API integration tests (TestClient, isolated SQLite DB)."""
from fastapi.testclient import TestClient

from app.main import app

client = TestClient(app)


def test_health():
    r = client.get("/health")
    assert r.status_code == 200
    assert r.json()["mode"] == "paper-trading-only"


def test_auth_flow():
    email = "trader@example.com"
    r = client.post("/api/auth/register", json={"email": email, "password": "secret123"})
    assert r.status_code in (200, 400)  # 400 if re-run against same DB
    r = client.post("/api/auth/login", data={"username": email, "password": "secret123"})
    assert r.status_code == 200
    token = r.json()["access_token"]
    r = client.get("/api/auth/me", headers={"Authorization": f"Bearer {token}"})
    assert r.status_code == 200
    assert r.json()["email"] == email


def test_scan_creates_signals():
    r = client.post("/api/scanner/run")
    assert r.status_code == 200
    body = r.json()
    assert body["signals_created"] > 0

    r = client.get("/api/signals")
    signals = r.json()
    assert len(signals) > 0
    s = signals[0]
    # Options signals are CALL/PUT; swing/crypto signals are BUY/SELL
    assert s["direction"] in ("CALL", "PUT", "BUY", "SELL")
    assert s["signal_type"] in ("options", "swing", "crypto")
    assert s["status"] in ("approved", "rejected")
    # Direction vocabulary must match the signal type
    for sig in signals[:10]:
        if sig["signal_type"] == "options":
            assert sig["direction"] in ("CALL", "PUT")
        else:
            assert sig["direction"] in ("BUY", "SELL")

    r = client.get(f"/api/signals/{s['id']}")
    assert r.status_code == 200


def test_paper_trade_lifecycle():
    client.post("/api/scanner/run")
    approved = client.get("/api/signals", params={"status": "approved"}).json()
    if not approved:  # deterministic mock may reject all on some days
        return
    signal = approved[0]
    r = client.post("/api/paper-trades", json={"signal_id": signal["id"]})
    assert r.status_code == 200
    trade = r.json()
    assert trade["status"] == "open"
    assert trade["quantity"] > 0

    r = client.post("/api/paper-trades/mark")
    assert r.status_code == 200

    trades = client.get("/api/paper-trades").json()
    open_ids = [t["id"] for t in trades if t["status"] == "open"]
    if trade["id"] in open_ids:
        r = client.post(f"/api/paper-trades/{trade['id']}/close")
        assert r.status_code == 200
        assert r.json()["status"] == "closed"


def test_rejected_signal_cannot_be_traded():
    client.post("/api/scanner/run")
    rejected = client.get("/api/signals", params={"status": "rejected"}).json()
    if rejected:
        r = client.post("/api/paper-trades", json={"signal_id": rejected[0]["id"]})
        assert r.status_code == 400


def test_clear_signal_history_keeps_traded_signals():
    client.post("/api/scanner/run")
    before = client.get("/api/signals").json()
    assert len(before) > 0
    trades = client.get("/api/paper-trades").json()
    traded_signal_ids = {t["signal_id"] for t in trades if t["signal_id"]}

    r = client.request("DELETE", "/api/signals/history")
    assert r.status_code == 200
    body = r.json()
    assert body["signals_deleted"] >= 0

    after = client.get("/api/signals").json()
    remaining_ids = {s["id"] for s in after}
    assert traded_signal_ids.issubset(remaining_ids)  # learning data preserved
    assert len(after) == len(traded_signal_ids)


def test_risk_and_reports():
    r = client.get("/api/risk/rules")
    assert r.json()["min_risk_reward"] >= 1.0
    r = client.get("/api/risk/summary")
    assert "account_equity" in r.json()
    r = client.post("/api/reports/generate")
    assert r.status_code == 200
    assert "Daily Report" in r.json()["summary"]
    r = client.get("/api/dashboard/summary")
    assert r.status_code == 200
    assert "portfolio" in r.json()
