"""Tests for the Polygon.io market data adapter.

Validates request building, response parsing, and error handling.
"""
from services.adapters.market_adapter import MarketDataAdapter, PolygonMarketAdapter

# --- Fake Polygon responses ---

PREV_BARS_RESPONSE = {
    "ticker": "AAPL",
    "queryCount": 1,
    "resultsCount": 1,
    "adjusted": True,
    "results": [
        {
            "T": "AAPL",
            "v": 58_350_544,
            "vw": 171.5322,
            "o": 171.0,
            "c": 172.28,
            "h": 173.1,
            "l": 170.5,
            "t": 1712793600000,
            "n": 620_123,
        }
    ],
    "status": "OK",
    "request_id": "req-abc-123",
}

TICKER_DETAILS_RESPONSE = {
    "results": {
        "ticker": "AAPL",
        "name": "Apple Inc.",
        "market": "stocks",
        "locale": "us",
        "primary_exchange": "XNAS",
        "type": "CS",
        "currency_name": "usd",
        "market_cap": 2_700_000_000_000,
    },
    "status": "OK",
    "request_id": "req-def-456",
}

RANGE_BARS_RESPONSE = {
    "ticker": "AAPL",
    "queryCount": 3,
    "resultsCount": 3,
    "adjusted": True,
    "results": [
        {"T": "AAPL", "o": 170.0, "c": 171.0, "h": 172.0, "l": 169.5, "v": 50_000_000, "t": 1712620800000},
        {"T": "AAPL", "o": 171.0, "c": 172.0, "h": 173.0, "l": 170.0, "v": 55_000_000, "t": 1712707200000},
        {"T": "AAPL", "o": 172.0, "c": 172.5, "h": 174.0, "l": 171.0, "v": 48_000_000, "t": 1712793600000},
    ],
    "status": "OK",
    "request_id": "req-ghi-789",
}


class TestPolygonSourceType:
    def test_source_type(self):
        adapter = PolygonMarketAdapter(api_key="k")
        assert adapter.source_type() == "market_api"

    def test_inherits_market_data_adapter(self):
        assert issubclass(PolygonMarketAdapter, MarketDataAdapter)

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


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

    def test_prev_bars_default(self):
        url, params = self.adapter._build_request("AAPL", "prev_bars", {})
        assert url == "https://api.polygon.io/v2/aggs/ticker/AAPL/prev"
        assert params["apiKey"] == "test-key"

    def test_prev_bars_with_adjusted(self):
        url, params = self.adapter._build_request("AAPL", "prev_bars", {"adjusted": False})
        assert params["adjusted"] == "false"

    def test_range_bars(self):
        config = {
            "multiplier": 1,
            "timespan": "day",
            "from_date": "2026-04-01",
            "to_date": "2026-04-10",
            "adjusted": True,
            "limit": 50,
            "sort": "asc",
        }
        url, params = self.adapter._build_request("AAPL", "range_bars", config)
        assert "/v2/aggs/ticker/AAPL/range/1/day/2026-04-01/2026-04-10" in url
        assert params["adjusted"] == "true"
        assert params["limit"] == "50"
        assert params["sort"] == "asc"

    def test_ticker_details(self):
        url, params = self.adapter._build_request("MSFT", "ticker_details", {})
        assert url == "https://api.polygon.io/v3/reference/tickers/MSFT"
        assert params["apiKey"] == "test-key"

    def test_unknown_endpoint_defaults_to_prev(self):
        url, _ = self.adapter._build_request("AAPL", "unknown_thing", {})
        assert "/v2/aggs/ticker/AAPL/prev" in url

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


class TestPolygonExtractItems:
    def setup_method(self):
        self.adapter = PolygonMarketAdapter(api_key="k")

    def test_extract_prev_bars(self):
        items = self.adapter._extract_items(PREV_BARS_RESPONSE, "prev_bars")
        assert len(items) == 1
        assert items[0]["T"] == "AAPL"

    def test_extract_range_bars(self):
        items = self.adapter._extract_items(RANGE_BARS_RESPONSE, "range_bars")
        assert len(items) == 3

    def test_extract_ticker_details(self):
        items = self.adapter._extract_items(TICKER_DETAILS_RESPONSE, "ticker_details")
        assert len(items) == 1
        assert items[0]["ticker"] == "AAPL"

    def test_extract_empty_results_list(self):
        items = self.adapter._extract_items({"results": [], "status": "OK"}, "prev_bars")
        assert items == []

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

    def test_extract_ticker_details_empty(self):
        items = self.adapter._extract_items({"results": {}, "status": "OK"}, "ticker_details")
        assert items == []


class TestPolygonErrorResult:
    def test_error_result_fields(self):
        adapter = PolygonMarketAdapter(api_key="k")
        result = adapter._error_result("AAPL", "something broke", 42.5, http_status=500, raw=b"err")
        assert not result.ok
        assert result.error == "something broke"
        assert result.http_status == 500
        assert result.response_time_ms == 42.5
        assert result.raw_payload == b"err"
        assert result.metadata["provider"] == "polygon"

    def test_error_result_defaults(self):
        adapter = PolygonMarketAdapter(api_key="k")
        result = adapter._error_result("AAPL", "timeout", 100.0)
        assert result.http_status is None
        assert result.raw_payload == b""
