"""Tests for /api/v1/preferences/card-modes endpoints."""

import pytest

from ledgrab.config import get_config


@pytest.fixture(scope="module")
def client():
    """TestClient with auth header read at fixture-build time.

    Mirrors test_preferences_api.py — the auth key is resolved here so
    any singleton mutation during pytest collection cannot leave us with
    a stale Bearer header.
    """
    from fastapi.testclient import TestClient

    from ledgrab.main import app

    api_key = next(iter(get_config().auth.api_keys.values()), "")
    with TestClient(app, raise_server_exceptions=False) as c:
        if api_key:
            c.headers["Authorization"] = f"Bearer {api_key}"
        yield c


def _prefs(surfaces: dict[str, str] | None = None) -> dict:
    return {"version": 1, "surfaces": surfaces or {}}


def test_get_default_empty(client):
    """When nothing is saved, GET returns {}."""
    client.delete("/api/v1/preferences/card-modes")
    resp = client.get("/api/v1/preferences/card-modes")
    assert resp.status_code == 200
    assert resp.json() == {}


def test_put_then_get_round_trip(client):
    """PUT a prefs object, GET it back verbatim."""
    body = _prefs({"led-devices": "dense", "led-targets": "comfortable"})
    put = client.put("/api/v1/preferences/card-modes", json=body)
    assert put.status_code == 200
    assert put.json() == {"ok": True}

    got = client.get("/api/v1/preferences/card-modes")
    assert got.status_code == 200
    assert got.json() == body


def test_put_rejects_missing_version(client):
    """Body without numeric version is rejected with 422."""
    resp = client.put(
        "/api/v1/preferences/card-modes",
        json={"surfaces": {"led-devices": "dense"}},
    )
    assert resp.status_code == 422


def test_put_rejects_invalid_mode(client):
    """A mode value outside the allowed set is rejected with 422."""
    resp = client.put(
        "/api/v1/preferences/card-modes",
        json=_prefs({"led-devices": "extreme"}),
    )
    assert resp.status_code == 422


def test_put_rejects_non_dict_surfaces(client):
    """`surfaces` must be an object, not an array or string."""
    resp = client.put(
        "/api/v1/preferences/card-modes",
        json={"version": 1, "surfaces": ["led-devices", "dense"]},
    )
    assert resp.status_code == 422


def test_put_accepts_empty_surfaces(client):
    """An empty surfaces map is a valid (no-override) state."""
    resp = client.put("/api/v1/preferences/card-modes", json=_prefs({}))
    assert resp.status_code == 200


def test_put_accepts_unknown_surface_keys(client):
    """Surface keys are an open registry — any non-empty string is OK."""
    body = _prefs(
        {
            "led-devices": "compact",
            "automations": "dense",
            "weather-sources": "comfortable",
            "future-surface-v2": "compact",
        }
    )
    resp = client.put("/api/v1/preferences/card-modes", json=body)
    assert resp.status_code == 200
    got = client.get("/api/v1/preferences/card-modes").json()
    assert got["surfaces"]["future-surface-v2"] == "compact"


def test_put_accepts_row_mode(client):
    """`row` is a valid mode (added alongside the original three)."""
    body = _prefs({"led-devices": "row"})
    resp = client.put("/api/v1/preferences/card-modes", json=body)
    assert resp.status_code == 200
    got = client.get("/api/v1/preferences/card-modes").json()
    assert got["surfaces"]["led-devices"] == "row"


def test_delete_clears(client):
    """DELETE wipes saved prefs so the next GET returns empty."""
    client.put(
        "/api/v1/preferences/card-modes",
        json=_prefs({"led-devices": "dense"}),
    )
    deleted = client.delete("/api/v1/preferences/card-modes")
    assert deleted.status_code == 200
    after = client.get("/api/v1/preferences/card-modes")
    assert after.status_code == 200
    assert after.json() == {}
