"""Unit tests for FinnhubFundamentalProvider unit conversions."""

from __future__ import annotations

from unittest.mock import AsyncMock, patch

import httpx
import pytest

from app.providers.fundamentals_chain import FinnhubFundamentalProvider


def _mock_response(status_code: int, json_data: object = None) -> httpx.Response:
    return httpx.Response(
        status_code=status_code,
        json=json_data if json_data is not None else {},
        request=httpx.Request("GET", "https://example.com"),
    )


@pytest.fixture
def provider() -> FinnhubFundamentalProvider:
    return FinnhubFundamentalProvider(api_key="test-key")


@pytest.mark.asyncio
async def test_finnhub_market_cap_converted_from_millions_to_dollars(provider):
    """Finnhub marketCapitalization is in millions — store absolute USD.

    SPCX-scale example: ~$1.8T → Finnhub reports 1_800_000 (millions).
    Without conversion the UI showed 1.8M / micro cap.
    """
    profile = {"marketCapitalization": 1_800_000}  # millions → $1.8T
    metrics = {"metric": {"peTTM": 40.0, "revenueGrowthTTMYoy": 25.0}}
    earnings = [{"surprisePercent": 2.5}]
    calendar = {"earningsCalendar": []}

    async def mock_get(url, params=None):
        if "profile2" in url:
            return _mock_response(200, profile)
        if "stock/metric" in url:
            return _mock_response(200, metrics)
        if "stock/earnings" in url:
            return _mock_response(200, earnings)
        if "calendar/earnings" in url:
            return _mock_response(200, calendar)
        return _mock_response(200, {})

    with patch("app.providers.fundamentals_chain.httpx.AsyncClient") as MockClient:
        instance = AsyncMock()
        instance.get.side_effect = mock_get
        instance.__aenter__ = AsyncMock(return_value=instance)
        instance.__aexit__ = AsyncMock(return_value=False)
        MockClient.return_value = instance

        result = await provider.fetch_fundamentals("SPCX")

    assert result.market_cap == 1_800_000 * 1_000_000  # $1.8T
    assert result.pe_ratio == 40.0
    assert result.revenue_growth == 25.0
    assert result.earnings_surprise == 2.5


@pytest.mark.asyncio
async def test_finnhub_market_cap_none_when_missing(provider):
    profile: dict = {}
    metrics = {"metric": {}}
    earnings: list = []
    calendar = {"earningsCalendar": []}

    async def mock_get(url, params=None):
        if "profile2" in url:
            return _mock_response(200, profile)
        if "stock/metric" in url:
            return _mock_response(200, metrics)
        if "stock/earnings" in url:
            return _mock_response(200, earnings)
        if "calendar/earnings" in url:
            return _mock_response(200, calendar)
        return _mock_response(200, {})

    with patch("app.providers.fundamentals_chain.httpx.AsyncClient") as MockClient:
        instance = AsyncMock()
        instance.get.side_effect = mock_get
        instance.__aenter__ = AsyncMock(return_value=instance)
        instance.__aexit__ = AsyncMock(return_value=False)
        MockClient.return_value = instance

        result = await provider.fetch_fundamentals("XYZ")

    assert result.market_cap is None
    assert "market_cap" in result.unavailable_fields
