"""Tests for the synchronous WeatherClient (all HTTP mocked)."""

import pytest
import responses
from tests.conftest import BASE

from accuweather_client import WeatherClient


def make_client(token, **kwargs) -> WeatherClient:
    kwargs.setdefault("city", "sydney")
    return WeatherClient(token=token, **kwargs)


def mock_location(location_payload):
    responses.get(f"{BASE}/locations/v1/cities/search", json=location_payload)


def test_constructor_makes_no_network_calls(token):
    # No `responses` activation here: any request would raise.
    client = make_client(token)
    assert client.city == "sydney"


def test_constructor_validates_location_arguments(token):
    with pytest.raises(ValueError, match="not both"):
        WeatherClient(token=token, city="sydney", poi="Opera House")
    with pytest.raises(ValueError):
        WeatherClient(token=token)
    with pytest.raises(ValueError):
        WeatherClient(token=token, lat=51.0)


@responses.activate
def test_location_resolved_lazily_and_cached(token, location_payload):
    mock_location(location_payload)
    client = make_client(token)
    assert client.location_key == "22889"
    assert client.location.LocalizedName == "Sydney"
    # Second access must not trigger a second HTTP call.
    assert len(responses.calls) == 1


@responses.activate
def test_get_current_conditions(token, location_payload, conditions_payload):
    mock_location(location_payload)
    responses.get(
        f"{BASE}/currentconditions/v1/22889", json=conditions_payload
    )
    conditions = make_client(token).get_current_conditions()
    assert "sunny" in conditions.current_conditions
    assert "coming" in conditions.current_conditions  # typo fixed in v2
    assert conditions.temperature == 17.2
    assert conditions.weather_text == "Sunny"


@responses.activate
def test_get_5day_forecast(token, location_payload, forecast_payload):
    mock_location(location_payload)
    responses.get(
        f"{BASE}/forecasts/v1/daily/5day/22889", json=forecast_payload
    )
    forecast = make_client(token).get_5day_forecast()
    assert forecast.text == "Pleasant this weekend"
    assert forecast.forecast_tomorrow == (
        "Partly sunny with showers, max temp is 18.9C and 25% chance of rain."
    )


@responses.activate
def test_daily_forecast_lengths_hit_matching_endpoints(
    token, location_payload, forecast_payload
):
    mock_location(location_payload)
    for days in (1, 10, 15):
        responses.get(
            f"{BASE}/forecasts/v1/daily/{days}day/22889",
            json=forecast_payload,
        )
    client = make_client(token)
    client.get_1day_forecast()
    client.get_10day_forecast()
    client.get_15day_forecast()
    with pytest.raises(ValueError, match="days must be one of"):
        client.get_daily_forecast(days=7)


@responses.activate
def test_get_hourly_forecast(token, location_payload, hourly_payload):
    mock_location(location_payload)
    responses.get(
        f"{BASE}/forecasts/v1/hourly/12hour/22889", json=hourly_payload
    )
    hourly = make_client(token).get_hourly_forecast_12h()
    assert len(hourly.output) == 2
    assert hourly.output[0].temperature.value == 16.7
    assert hourly.output[1].precipitation_type == "Rain"
    with pytest.raises(ValueError, match="hours must be one of"):
        make_client(token).get_hourly_forecast(hours=7)


@responses.activate
def test_get_alerts(token, location_payload, alerts_payload):
    mock_location(location_payload)
    responses.get(f"{BASE}/alerts/v1/22889", json=alerts_payload)
    alerts = make_client(token).get_alerts()
    assert alerts.count == 1
    assert alerts.descriptions == ["Strong Wind Warning"]
    assert "Strong Wind Warning" in str(alerts)


@responses.activate
def test_get_indices_filter(token, location_payload, indices_payload):
    mock_location(location_payload)
    responses.get(f"{BASE}/indices/v1/daily/1day/22889", json=indices_payload)
    indices = make_client(token).get_indices()
    running = indices.get("running")
    assert len(running) == 1
    assert running[0]["Category"] == "Very Good"


@responses.activate
def test_get_historical_conditions(
    token, location_payload, conditions_payload
):
    mock_location(location_payload)
    responses.get(
        f"{BASE}/currentconditions/v1/22889/historical/24",
        json=conditions_payload,
    )
    historical = make_client(token).get_historical_conditions(hours=24)
    assert historical.to_dict()[0]["WeatherText"] == "Sunny"
    with pytest.raises(ValueError):
        make_client(token).get_historical_conditions(hours=12)


@responses.activate
def test_cache_ttl_prevents_duplicate_requests(
    token, location_payload, conditions_payload
):
    mock_location(location_payload)
    responses.get(
        f"{BASE}/currentconditions/v1/22889", json=conditions_payload
    )
    client = make_client(token, cache_ttl=600)
    client.get_current_conditions()
    client.get_current_conditions()
    # 1 location call + 1 conditions call, second conditions call cached.
    assert len(responses.calls) == 2


@responses.activate
def test_metric_and_language_params_forwarded(token, location_payload):
    mock_location(location_payload)
    responses.get(
        f"{BASE}/forecasts/v1/daily/5day/22889",
        json={
            "Headline": {
                "EffectiveDate": "2026-07-31T07:00:00+10:00",
                "EffectiveEpochDate": 1,
                "Severity": 4,
                "Text": "x",
            },
            "DailyForecasts": [],
        },
    )
    client = make_client(token, metric=False, language="nl-nl")
    client.get_5day_forecast()
    url = responses.calls[-1].request.url
    assert "metric=false" in url
    assert "language=nl-nl" in url
