"""Integration tests for the Query API — all 17 frontend-facing endpoints.

Validates every GET endpoint the frontend calls against the live sandbox
with deterministic seed data.  Uses the ``query_client`` and ``seed_ids``
fixtures from conftest.py.
"""

import pytest

pytestmark = pytest.mark.asyncio


# ---------------------------------------------------------------------------
# 1–3  Companies
# ---------------------------------------------------------------------------


class TestQueryAPICompanies:
    """Endpoints: /api/companies, /api/companies/{id}, /api/companies/{id}/sources."""

    async def test_list_companies(self, query_client, seed_ids):
        """GET /api/companies — expect at least 5 seeded companies."""
        resp = await query_client.get("/api/companies")
        assert resp.status_code == 200
        data = resp.json()
        assert len(data) >= 5
        tickers = {c["ticker"] for c in data}
        assert {"AAPL", "MSFT", "JPM", "JNJ", "XOM"} <= tickers
        # Every company row must have core fields
        for c in data:
            assert "id" in c
            assert "legal_name" in c
            assert "sector" in c

    async def test_get_company(self, query_client, seed_ids):
        """GET /api/companies/{id} — detail for AAPL."""
        company_id = seed_ids["companies"]["AAPL"]
        resp = await query_client.get(f"/api/companies/{company_id}")
        assert resp.status_code == 200
        data = resp.json()
        assert data["ticker"] == "AAPL"
        assert data["legal_name"] == "Apple Inc"
        assert "aliases" in data
        assert "active_source_count" in data

    async def test_list_company_sources(self, query_client, seed_ids):
        """GET /api/companies/{id}/sources — AAPL has at least 1 source."""
        company_id = seed_ids["companies"]["AAPL"]
        resp = await query_client.get(f"/api/companies/{company_id}/sources")
        assert resp.status_code == 200
        data = resp.json()
        assert isinstance(data, list)
        assert len(data) >= 1
        assert "source_type" in data[0]


# ---------------------------------------------------------------------------
# 4–5  Documents
# ---------------------------------------------------------------------------


class TestQueryAPIDocuments:
    """Endpoints: /api/documents, /api/documents/{id}."""

    async def test_list_documents(self, query_client, seed_ids):
        """GET /api/documents — expect at least 10 seeded documents."""
        resp = await query_client.get("/api/documents")
        assert resp.status_code == 200
        data = resp.json()
        assert len(data) >= 10
        for doc in data:
            assert "id" in doc
            assert "document_type" in doc
            assert "title" in doc

    async def test_get_document(self, query_client, seed_ids):
        """GET /api/documents/{id} — detail with intelligence."""
        doc_id = seed_ids["documents"]["DOC_01"]
        resp = await query_client.get(f"/api/documents/{doc_id}")
        assert resp.status_code == 200
        data = resp.json()
        assert data["id"] == doc_id
        assert "title" in data
        assert "document_type" in data
        # Intelligence extraction should be present for seeded docs
        assert "intelligence" in data
        assert "company_mentions" in data


# ---------------------------------------------------------------------------
# 6–7  Trends
# ---------------------------------------------------------------------------


class TestQueryAPITrends:
    """Endpoints: /api/trends, /api/trends/{id}."""

    async def test_list_trends(self, query_client, seed_ids):
        """GET /api/trends — expect at least 5 seeded trend windows."""
        resp = await query_client.get("/api/trends")
        assert resp.status_code == 200
        data = resp.json()
        assert len(data) >= 5
        for t in data:
            assert "id" in t
            assert "trend_direction" in t
            assert "confidence" in t

    async def test_get_trend(self, query_client, seed_ids):
        """GET /api/trends/{id} — detail for first seeded trend."""
        trend_id = seed_ids["trends"]["TREND_01"]
        resp = await query_client.get(f"/api/trends/{trend_id}")
        assert resp.status_code == 200
        data = resp.json()
        assert data["id"] == trend_id
        assert data["trend_direction"] in ("bullish", "bearish", "mixed")
        assert 0 <= data["confidence"] <= 1


# ---------------------------------------------------------------------------
# 8–9  Recommendations
# ---------------------------------------------------------------------------


class TestQueryAPIRecommendations:
    """Endpoints: /api/recommendations, /api/recommendations/{id}."""

    async def test_list_recommendations(self, query_client, seed_ids):
        """GET /api/recommendations — expect at least 5 seeded recs."""
        resp = await query_client.get("/api/recommendations", params={"latest": "false"})
        assert resp.status_code == 200
        data = resp.json()
        assert len(data) >= 5
        for r in data:
            assert "id" in r
            assert "ticker" in r
            assert "action" in r
            assert "confidence" in r

    async def test_get_recommendation(self, query_client, seed_ids):
        """GET /api/recommendations/{id} — detail with evidence."""
        rec_id = seed_ids["recommendations"]["REC_01"]
        resp = await query_client.get(f"/api/recommendations/{rec_id}")
        assert resp.status_code == 200
        data = resp.json()
        assert data["id"] == rec_id
        assert "ticker" in data
        assert "thesis" in data
        assert "evidence" in data
        assert "risk_evaluation" in data


# ---------------------------------------------------------------------------
# 10–11  Orders
# ---------------------------------------------------------------------------


class TestQueryAPIOrders:
    """Endpoints: /api/orders, /api/orders/{id}."""

    async def test_list_orders(self, query_client, seed_ids):
        """GET /api/orders — expect at least 3 seeded orders."""
        resp = await query_client.get("/api/orders")
        assert resp.status_code == 200
        data = resp.json()
        assert len(data) >= 3
        statuses = {o["status"] for o in data}
        # Seed has filled, pending, cancelled
        assert len(statuses) >= 2
        for o in data:
            assert "id" in o
            assert "ticker" in o
            assert "side" in o

    async def test_get_order(self, query_client, seed_ids):
        """GET /api/orders/{id} — detail with events and audit trail."""
        order_id = seed_ids["orders"]["ORDER_01"]
        resp = await query_client.get(f"/api/orders/{order_id}")
        assert resp.status_code == 200
        data = resp.json()
        assert data["id"] == order_id
        assert "ticker" in data
        assert "events" in data
        assert isinstance(data["events"], list)
        assert "audit_trail" in data


# ---------------------------------------------------------------------------
# 12  Positions
# ---------------------------------------------------------------------------


class TestQueryAPIPositions:
    """Endpoint: /api/positions."""

    async def test_list_positions(self, query_client, seed_ids):
        """GET /api/positions — expect at least 2 seeded positions."""
        resp = await query_client.get("/api/positions")
        assert resp.status_code == 200
        data = resp.json()
        assert len(data) >= 2
        for p in data:
            assert "id" in p
            assert "ticker" in p
            assert "quantity" in p
            assert "unrealized_pnl" in p


# ---------------------------------------------------------------------------
# 13  Pipeline Health
# ---------------------------------------------------------------------------


class TestQueryAPIOps:
    """Endpoints: /api/ops/pipeline/health, /api/ops/ingestion/summary, /api/ops/sources/coverage-gaps."""

    async def test_pipeline_health(self, query_client, seed_ids):
        """GET /api/ops/pipeline/health — returns structured health data."""
        resp = await query_client.get("/api/ops/pipeline/health")
        assert resp.status_code == 200
        data = resp.json()
        assert "hours" in data
        assert "document_stages" in data
        assert "parsing" in data
        assert "extraction" in data
        assert "aggregation" in data
        assert "queue_depths" in data

    # -----------------------------------------------------------------------
    # 14  Ingestion Summary
    # -----------------------------------------------------------------------

    async def test_ingestion_summary(self, query_client, seed_ids):
        """GET /api/ops/ingestion/summary — returns ingestion stats."""
        resp = await query_client.get("/api/ops/ingestion/summary")
        assert resp.status_code == 200
        data = resp.json()
        assert "hours" in data
        assert "total_runs" in data
        assert "by_source_type" in data
        assert isinstance(data["by_source_type"], list)

    # -----------------------------------------------------------------------
    # 15  Coverage Gaps
    # -----------------------------------------------------------------------

    async def test_coverage_gaps(self, query_client, seed_ids):
        """GET /api/ops/sources/coverage-gaps — returns gap analysis."""
        resp = await query_client.get("/api/ops/sources/coverage-gaps")
        assert resp.status_code == 200
        data = resp.json()
        assert "missing_source_types" in data
        assert "stale_sources" in data
        assert isinstance(data["missing_source_types"], list)
        assert isinstance(data["stale_sources"], list)


# ---------------------------------------------------------------------------
# 16–17  Agents & Variants
# ---------------------------------------------------------------------------


class TestQueryAPIAgents:
    """Endpoints: /api/agents, /api/agents/{id}/variants."""

    async def test_list_agents(self, query_client, seed_ids):
        """GET /api/agents — expect at least 3 seeded agents."""
        resp = await query_client.get("/api/agents")
        assert resp.status_code == 200
        data = resp.json()
        assert len(data) >= 3
        for a in data:
            assert "id" in a
            assert "name" in a
            assert "slug" in a

    async def test_list_agent_variants(self, query_client, seed_ids):
        """GET /api/agents/{id}/variants — variants for the extractor agent."""
        agent_id = seed_ids["agents"]["extractor"]
        resp = await query_client.get(f"/api/agents/{agent_id}/variants")
        assert resp.status_code == 200
        data = resp.json()
        assert isinstance(data, list)
        assert len(data) >= 1
        for v in data:
            assert "id" in v
            assert "variant_name" in v
            assert v["agent_id"] == agent_id
