"""app.widgets.weather -- unit-level, no HTTP: constructs Widget/
WeatherWidgetConfig rows directly and monkeypatches the underlying fetch
call (get_or_refresh_weather_widget_data, whose own throttle/provider-
dispatch logic is covered by test_weather_providers.py and exercised at
the HTTP layer in test_widget_config_and_queue_endpoints.py) -- this file
is about the widget wiring itself: does render() produce a correctly-
sized image for each of the four modes, does it fall back to a
placeholder when unconfigured, does check_now force a refetch."""

from __future__ import annotations

import time

from app import grid, widgets
from app.models import Frame, WeatherWidgetConfig, Widget


def _make_widget(db_session, **cfg_kwargs) -> tuple[Frame, Widget]:
    frame = db_session.get(Frame, 1)
    widget = Widget(frame_id=frame.id, widget_type="weather", x=0, y=0, w=2, h=2,
                    sort_order=0, created_at=time.time())
    db_session.add(widget)
    db_session.flush()
    db_session.add(WeatherWidgetConfig(widget_id=widget.id, **cfg_kwargs))
    db_session.commit()
    return frame, widget


def test_render_falls_back_to_placeholder_when_not_configured(db_session, monkeypatch):
    frame, widget = _make_widget(db_session, mode="current")
    monkeypatch.setattr(widgets.weather, "get_or_refresh_weather_widget_data", lambda db, frame, widget: None)

    img = widgets.weather.render(db_session, frame, widget, 300, 200)
    assert img.size == (300, 200)
    assert img.mode == "RGB"


def test_render_current_mode(db_session, monkeypatch):
    frame, widget = _make_widget(db_session, mode="current", city_label="Portland")
    monkeypatch.setattr(widgets.weather, "get_or_refresh_weather_widget_data",
                        lambda db, frame, widget: {"temp": 72.0, "category": "clear"})

    img = widgets.weather.render(db_session, frame, widget, 300, 200)
    assert img.size == (300, 200)
    assert img.mode == "RGB"


def test_render_hourly_mode(db_session, monkeypatch):
    frame, widget = _make_widget(db_session, mode="hourly", city_label="Seattle", hourly_interval_hours=4)
    hourly = [{"time": f"2026-07-27T{h:02d}:00", "temp": 60 + h, "category": "rain"} for h in range(24)]
    monkeypatch.setattr(widgets.weather, "get_or_refresh_weather_widget_data", lambda db, frame, widget: hourly)

    img = widgets.weather.render(db_session, frame, widget, 400, 300)
    assert img.size == (400, 300)


def test_render_daily_mode(db_session, monkeypatch):
    frame, widget = _make_widget(db_session, mode="daily", city_label="Denver", daily_days=5)
    daily = {f"2026-07-{27 + i}": {"high": 70 + i, "low": 50 + i, "category": "clear"} for i in range(5)}
    monkeypatch.setattr(widgets.weather, "get_or_refresh_weather_widget_data", lambda db, frame, widget: daily)

    img = widgets.weather.render(db_session, frame, widget, 400, 300)
    assert img.size == (400, 300)


def test_render_multi_city_mode(db_session, monkeypatch):
    """cached entries carry the full disambiguated geocoder label (see
    get_or_refresh_weather_widget_data/weather.geocode_city) -- render()
    must still produce a correctly-sized image (weather_render.
    build_multi_city shortens to just the city name for display, same as
    calendar_render.py's _weather_for_day)."""
    frame, widget = _make_widget(db_session, mode="multi_city")
    cities = [
        {"label": "Portland, Oregon, United States", "high": 75, "low": 55, "category": "clear"},
        {"label": "Seattle, Washington, United States", "high": 65, "low": 50, "category": "rain"},
    ]
    monkeypatch.setattr(widgets.weather, "get_or_refresh_weather_widget_data", lambda db, frame, widget: cities)

    img = widgets.weather.render(db_session, frame, widget, 400, 300)
    assert img.size == (400, 300)


def test_render_at_minimum_grid_footprint(db_session, monkeypatch):
    """grid.MIN_FOOTPRINT["weather"] is (2, 2) cells -- on an 8x5 grid
    against a full 800x480 panel that's a 200x192 box, the smallest a
    weather widget can actually be placed at."""
    assert grid.MIN_FOOTPRINT["weather"] == (2, 2)
    frame, widget = _make_widget(db_session, mode="current")
    monkeypatch.setattr(widgets.weather, "get_or_refresh_weather_widget_data",
                        lambda db, frame, widget: {"temp": 72.0, "category": "clear"})

    img = widgets.weather.render(db_session, frame, widget, 200, 192)
    assert img.size == (200, 192)


def test_check_now_forces_a_refetch(db_session, monkeypatch):
    frame, widget = _make_widget(db_session, mode="current")
    calls = []

    def _fake_refresh(db, frame, widget, force=False):
        calls.append(force)
        return {"temp": 70.0, "category": "clear"}

    monkeypatch.setattr(widgets.weather, "get_or_refresh_weather_widget_data", _fake_refresh)
    widgets.weather.ACTIONS["check_now"](db_session, frame, widget)
    assert calls == [True]


def test_action_labels():
    assert set(widgets.weather.ACTIONS.keys()) == {"check_now"}
    assert widgets.weather.ACTION_LABELS == {"check_now": "Check for updates"}
