import httpx
import pytest
from httpx import ASGITransport, AsyncClient

from app.main import app


@pytest.mark.asyncio
async def test_system_config_returns_location_and_weather(monkeypatch):
    async def fake_get_config(self):
        return {
            'location': 'wuhan',
            'weather_code': 3,
            'weather_summary': 'Overcast 22°C',
        }

    monkeypatch.setattr('app.routers.system.SystemService.get_config', fake_get_config)
    transport = ASGITransport(app=app)

    async with AsyncClient(transport=transport, base_url='http://testserver') as client:
        response = await client.get('/api/system/config')

    assert response.status_code == 200
    assert response.json() == {
        'location': 'wuhan',
        'weather_code': 3,
        'weather_summary': 'Overcast 22°C',
    }


@pytest.mark.asyncio
async def test_system_config_gracefully_returns_unavailable_weather(monkeypatch):
    async def fake_get_config(self):
        return {
            'location': 'wuhan',
            'weather_code': None,
            'weather_summary': 'Weather unavailable',
        }

    monkeypatch.setattr('app.routers.system.SystemService.get_config', fake_get_config)
    transport = ASGITransport(app=app)

    async with AsyncClient(transport=transport, base_url='http://testserver') as client:
        response = await client.get('/api/system/config')

    assert response.status_code == 200
    assert response.json() == {
        'location': 'wuhan',
        'weather_code': None,
        'weather_summary': 'Weather unavailable',
    }


class FakeWeatherResponse:
    def __init__(self, payload: dict, status_code: int = 200):
        self._payload = payload
        self.status_code = status_code

    def raise_for_status(self):
        if self.status_code >= 400:
            raise httpx.HTTPStatusError(
                'request failed',
                request=httpx.Request('GET', 'https://wttr.in/wuhan?format=j1'),
                response=httpx.Response(self.status_code, request=httpx.Request('GET', 'https://wttr.in/wuhan?format=j1')),
            )

    def json(self):
        return self._payload


class FakeAsyncClient:
    def __init__(self, *, response=None, error=None, **kwargs):
        self._response = response
        self._error = error

    async def __aenter__(self):
        return self

    async def __aexit__(self, exc_type, exc, tb):
        return False

    async def get(self, url, *, params=None):
        if self._error is not None:
            raise self._error
        return self._response


@pytest.mark.asyncio
async def test_system_service_get_config_fetches_weather(monkeypatch):
    monkeypatch.setattr(
        'app.services.system_service.httpx.AsyncClient',
        lambda **kwargs: FakeAsyncClient(
            response=FakeWeatherResponse({'current_condition': [{'weatherCode': '61', 'temp_C': '18'}]}),
            **kwargs,
        ),
    )

    from app.services.system_service import SystemService

    service = SystemService()
    monkeypatch.setattr(service._settings, 'LOCATION', 'wuhan')

    payload = await service.get_config()

    assert payload == {
        'location': 'wuhan',
        'weather_code': 61,
        'weather_summary': 'Rain 18°C',
    }


@pytest.mark.asyncio
async def test_system_service_get_config_handles_weather_failure(monkeypatch):
    monkeypatch.setattr(
        'app.services.system_service.httpx.AsyncClient',
        lambda **kwargs: FakeAsyncClient(error=httpx.TimeoutException('timed out'), **kwargs),
    )

    from app.services.system_service import SystemService

    service = SystemService()
    monkeypatch.setattr(service._settings, 'LOCATION', 'wuhan')

    payload = await service.get_config()

    assert payload == {
        'location': 'wuhan',
        'weather_code': None,
        'weather_summary': 'Weather unavailable',
    }
