"""Tests for the Polygon.io news adapter.

Validates request building, response parsing, and error handling.
"""
from services.adapters.news_adapter import NewsDataAdapter, PolygonNewsAdapter

# --- Fake Polygon news responses ---

NEWS_RESPONSE = {
    "results": [
        {
            "id": "abc123",
            "publisher": {"name": "Reuters", "homepage_url": "https://reuters.com"},
            "title": "Apple Reports Record Revenue",
            "article_url": "https://reuters.com/apple-record",
            "tickers": ["AAPL"],
            "published_utc": "2026-04-10T14:30:00Z",
            "description": "Apple Inc. reported record quarterly revenue.",
            "keywords": ["earnings", "apple", "revenue"],
        },
        {
            "id": "def456",
            "publisher": {"name": "Bloomberg", "homepage_url": "https://bloomberg.com"},
            "title": "Apple Supply Chain Update",
            "article_url": "https://bloomberg.com/apple-supply",
            "tickers": ["AAPL", "TSM"],
            "published_utc": "2026-04-10T12:00:00Z",
            "description": "Supply chain adjustments for upcoming product cycle.",
            "keywords": ["supply_chain", "apple"],
        },
    ],
    "status": "OK",
    "request_id": "req-news-001",
    "count": 2,
    "next_url": "https://api.polygon.io/v2/reference/news?cursor=abc",
}

EMPTY_NEWS_RESPONSE = {
    "results": [],
    "status": "OK",
    "request_id": "req-news-002",
    "count": 0,
}


class TestPolygonNewsSourceType:
    def test_source_type(self):
        adapter = PolygonNewsAdapter(api_key="k")
        assert adapter.source_type() == "news_api"

    def test_inherits_news_data_adapter(self):
        assert issubclass(PolygonNewsAdapter, NewsDataAdapter)

    def test_bucket_name(self):
        adapter = PolygonNewsAdapter(api_key="k")
        assert adapter.bucket_name() == "stonks-raw-news"


class TestPolygonNewsBuildRequest:
    def setup_method(self):
        self.adapter = PolygonNewsAdapter(api_key="test-key", base_url="https://api.polygon.io")

    def test_default_request(self):
        url, params = self.adapter._build_request("AAPL", {})
        assert url == "https://api.polygon.io/v2/reference/news"
        assert params["apiKey"] == "test-key"
        assert params["ticker"] == "AAPL"
        assert params["limit"] == "20"

    def test_custom_limit(self):
        _, params = self.adapter._build_request("AAPL", {"limit": 50})
        assert params["limit"] == "50"

    def test_limit_capped_at_1000(self):
        _, params = self.adapter._build_request("AAPL", {"limit": 5000})
        assert params["limit"] == "1000"

    def test_order_param(self):
        _, params = self.adapter._build_request("AAPL", {"order": "asc"})
        assert params["order"] == "asc"

    def test_date_filters(self):
        config = {
            "published_utc_gte": "2026-04-01",
            "published_utc_lte": "2026-04-10",
        }
        _, params = self.adapter._build_request("AAPL", config)
        assert params["published_utc.gte"] == "2026-04-01"
        assert params["published_utc.lte"] == "2026-04-10"

    def test_no_date_filters_when_absent(self):
        _, params = self.adapter._build_request("AAPL", {})
        assert "published_utc.gte" not in params
        assert "published_utc.lte" not in params

    def test_trailing_slash_stripped(self):
        adapter = PolygonNewsAdapter(api_key="k", base_url="https://api.polygon.io/")
        url, _ = adapter._build_request("AAPL", {})
        assert "//v2" not in url


class TestPolygonNewsExtractItems:
    def setup_method(self):
        self.adapter = PolygonNewsAdapter(api_key="k")

    def test_extract_articles(self):
        items = self.adapter._extract_items(NEWS_RESPONSE)
        assert len(items) == 2
        assert items[0]["title"] == "Apple Reports Record Revenue"
        assert items[1]["tickers"] == ["AAPL", "TSM"]

    def test_extract_empty_results(self):
        items = self.adapter._extract_items(EMPTY_NEWS_RESPONSE)
        assert items == []

    def test_extract_missing_results_key(self):
        items = self.adapter._extract_items({"status": "OK"})
        assert items == []

    def test_extract_non_list_results(self):
        items = self.adapter._extract_items({"results": "unexpected"})
        assert items == []


class TestPolygonNewsErrorResult:
    def test_error_result_fields(self):
        adapter = PolygonNewsAdapter(api_key="k")
        result = adapter._error_result("AAPL", "rate limited", 150.0, http_status=429, raw=b"slow down")
        assert not result.ok
        assert result.error == "rate limited"
        assert result.http_status == 429
        assert result.response_time_ms == 150.0
        assert result.raw_payload == b"slow down"
        assert result.metadata["provider"] == "polygon"
        assert result.source_type == "news_api"

    def test_error_result_defaults(self):
        adapter = PolygonNewsAdapter(api_key="k")
        result = adapter._error_result("MSFT", "timeout", 200.0)
        assert result.http_status is None
        assert result.raw_payload == b""
        assert result.ticker == "MSFT"
