"""Integration tests for Trading Engine — extended coverage.

Validates configuration round-trips, pause/resume lifecycle, metrics
consistency, notification config, decision filtering, and override
order validation against the live sandbox.

Uses the ``trading_client`` fixture from conftest.py.
"""

import pytest

pytestmark = pytest.mark.asyncio


# ---------------------------------------------------------------------------
# 1  Config Round-Trip
# ---------------------------------------------------------------------------


class TestTradingConfigRoundTrip:
    """PUT config → GET status — verify risk_tier reflected."""

    async def test_config_round_trip(self, trading_client):
        """PUT config → GET status — verify risk_tier reflected."""
        # Set to aggressive
        resp = await trading_client.put(
            "/api/trading/config", json={"risk_tier": "aggressive"}
        )
        assert resp.status_code == 200
        # Verify in status
        status_resp = await trading_client.get("/api/trading/status")
        assert status_resp.status_code == 200
        assert status_resp.json()["risk_tier"] == "aggressive"
        # Restore to moderate
        await trading_client.put(
            "/api/trading/config", json={"risk_tier": "moderate"}
        )


# ---------------------------------------------------------------------------
# 2  Pause/Resume Round-Trip
# ---------------------------------------------------------------------------


class TestTradingPauseResumeRoundTrip:
    """POST pause → GET status → POST resume → GET status."""

    async def test_pause_resume_round_trip(self, trading_client):
        """POST pause → GET status → POST resume → GET status."""
        # Pause
        resp = await trading_client.post("/api/trading/pause")
        assert resp.status_code == 200
        # Verify paused
        status_resp = await trading_client.get("/api/trading/status")
        assert status_resp.status_code == 200
        assert status_resp.json()["paused"] is True
        # Resume
        resp2 = await trading_client.post("/api/trading/resume")
        assert resp2.status_code == 200
        # Verify resumed
        status_resp2 = await trading_client.get("/api/trading/status")
        assert status_resp2.status_code == 200
        assert status_resp2.json()["paused"] is False


# ---------------------------------------------------------------------------
# 3  Metrics Consistency
# ---------------------------------------------------------------------------


class TestTradingMetricsConsistency:
    """GET /api/trading/metrics — fields are present and non-negative."""

    async def test_metrics_consistency(self, trading_client):
        """GET /api/trading/metrics — all fields present and non-negative."""
        resp = await trading_client.get("/api/trading/metrics")
        assert resp.status_code == 200
        data = resp.json()
        assert data["total_portfolio_value"] >= 0
        assert data["active_pool"] >= 0
        assert data["reserve_pool"] >= 0
        # active_pool + reserve_pool should not exceed total
        assert data["active_pool"] + data["reserve_pool"] <= data["total_portfolio_value"] + 1.0


# ---------------------------------------------------------------------------
# 4  Metrics History
# ---------------------------------------------------------------------------


class TestTradingMetricsHistoryExtended:
    """GET /api/trading/metrics/history — returns portfolio snapshots."""

    async def test_metrics_history_snapshots(self, trading_client):
        """GET /api/trading/metrics/history — returns portfolio snapshots."""
        resp = await trading_client.get("/api/trading/metrics/history")
        assert resp.status_code == 200
        data = resp.json()
        assert isinstance(data, list)
        if len(data) >= 1:
            snap = data[0]
            assert "portfolio_value" in snap
            assert "snapshot_date" in snap


# ---------------------------------------------------------------------------
# 5  Notification Config Round-Trip
# ---------------------------------------------------------------------------


class TestTradingNotificationRoundTrip:
    """PUT → GET notification config round-trip."""

    async def test_notification_config_round_trip(self, trading_client):
        """PUT → GET notification config round-trip."""
        # Update phone number (which drives sms_enabled)
        resp = await trading_client.put(
            "/api/trading/notifications/config",
            json={"phone_number": "+15551234567"},
        )
        assert resp.status_code == 200
        # Verify GET returns config structure
        get_resp = await trading_client.get("/api/trading/notifications/config")
        assert get_resp.status_code == 200
        data = get_resp.json()
        assert "sms_enabled" in data
        assert "email_enabled" in data
        assert isinstance(data["sms_enabled"], bool)
        assert isinstance(data["email_enabled"], bool)


# ---------------------------------------------------------------------------
# 6  Notification History
# ---------------------------------------------------------------------------


class TestTradingNotificationHistory:
    """GET /api/trading/notifications/history — returns list."""

    async def test_notification_history(self, trading_client):
        """GET /api/trading/notifications/history — returns list."""
        resp = await trading_client.get("/api/trading/notifications/history")
        assert resp.status_code == 200
        data = resp.json()
        assert isinstance(data, list)


# ---------------------------------------------------------------------------
# 7  Decision Filtering
# ---------------------------------------------------------------------------


class TestTradingDecisionFiltering:
    """GET /api/trading/decisions with various filters."""

    async def test_decisions_filter_by_ticker(self, trading_client):
        """GET /api/trading/decisions?ticker=AAPL — only AAPL decisions."""
        resp = await trading_client.get(
            "/api/trading/decisions", params={"ticker": "AAPL"}
        )
        assert resp.status_code == 200
        data = resp.json()
        assert isinstance(data, list)
        for d in data:
            assert d["ticker"] == "AAPL"

    async def test_decisions_filter_by_limit(self, trading_client):
        """GET /api/trading/decisions?limit=1 — at most 1 decision."""
        resp = await trading_client.get(
            "/api/trading/decisions", params={"limit": "1"}
        )
        assert resp.status_code == 200
        data = resp.json()
        assert isinstance(data, list)
        assert len(data) <= 1

    async def test_decisions_filter_by_decision_type(self, trading_client):
        """GET /api/trading/decisions?decision=execute — only execute decisions."""
        resp = await trading_client.get(
            "/api/trading/decisions", params={"decision": "execute"}
        )
        assert resp.status_code == 200
        data = resp.json()
        assert isinstance(data, list)
        for d in data:
            assert d["decision"] == "execute"


# ---------------------------------------------------------------------------
# 8  Override Order Validation
# ---------------------------------------------------------------------------


class TestTradingOverrideValidation:
    """POST /api/trading/override/order — validation edge cases."""

    async def test_override_invalid_ticker(self, trading_client):
        """POST /api/trading/override/order — invalid ticker returns 422."""
        payload = {
            "ticker": "AAPL123",  # contains digits — should be rejected
            "side": "buy",
            "quantity": 1.0,
            "order_type": "market",
        }
        resp = await trading_client.post(
            "/api/trading/override/order", json=payload
        )
        assert resp.status_code == 422

    async def test_override_zero_quantity(self, trading_client):
        """POST /api/trading/override/order — zero quantity returns 422."""
        payload = {
            "ticker": "AAPL",
            "side": "buy",
            "quantity": 0,
            "order_type": "market",
        }
        resp = await trading_client.post(
            "/api/trading/override/order", json=payload
        )
        assert resp.status_code == 422

    async def test_override_valid_order(self, trading_client):
        """POST /api/trading/override/order — valid order returns 202 or structured error."""
        payload = {
            "ticker": "AAPL",
            "side": "buy",
            "quantity": 1.0,
            "order_type": "market",
        }
        resp = await trading_client.post(
            "/api/trading/override/order", json=payload
        )
        assert resp.status_code in (200, 202, 400, 422, 503)
        data = resp.json()
        if resp.status_code == 202:
            assert "job_id" in data
            assert data["status"] == "queued"
            assert data["ticker"] == "AAPL"
            assert data["side"] == "buy"
            assert data["quantity"] == 1.0
        else:
            assert isinstance(data, dict)
