"""GET/PATCH /auth/me — the interface language choice and what it resolves to.

The override lives in its own column, so a user who never touched the picker
must still get a usable language (the account's), and "auto" must put them back
there. The endpoint pair is stubbed at the DB boundary — the SQL itself is
covered by tests/unit/auth/test_deps.py.
"""

import pytest
from fastapi.testclient import TestClient

import navi.api.routes.auth as auth_routes
from navi.auth import User
from navi.auth.deps import require_user


@pytest.fixture
def api(monkeypatch):
    """TestClient over a signed-in user (account language: uk) with a stubbed store."""
    from navi.main import app

    user = User(id="u1", email="u1@navi.test", display_name="U", locale="uk")
    app.dependency_overrides[require_user] = lambda: user

    stored: dict[str, str | None] = {"value": None}
    written: list[tuple[str, str | None]] = []

    async def _get(_user_id):
        return stored["value"]

    async def _set(user_id, value):
        written.append((user_id, value))
        stored["value"] = value

    monkeypatch.setattr(auth_routes, "get_locale_override", _get)
    monkeypatch.setattr(auth_routes, "set_locale_override", _set)
    try:
        yield TestClient(app), stored, written
    finally:
        app.dependency_overrides.pop(require_user, None)


def test_me_follows_the_account_language_when_nothing_was_chosen(api):
    client, _stored, _written = api

    body = client.get("/auth/me").json()

    assert body["locale"] is None
    assert body["locale_effective"] == "uk"
    # The rest of the profile is unchanged by the new fields.
    assert body["id"] == "u1"
    assert body["email"] == "u1@navi.test"
    assert "profile_url" in body


def test_me_reports_the_chosen_language(api):
    client, stored, _written = api
    stored["value"] = "ru"

    body = client.get("/auth/me").json()

    assert body["locale"] == "ru"
    assert body["locale_effective"] == "ru"


def test_me_falls_back_to_english_for_an_unknown_account_tag(monkeypatch):
    """Accounts can carry tags Navi has no dictionary for — the interface must
    still come up in a language it can speak."""
    from navi.main import app

    app.dependency_overrides[require_user] = lambda: User(id="u2", email="u2@navi.test", locale="de")

    async def _no_override(_user_id):
        return None

    monkeypatch.setattr(auth_routes, "get_locale_override", _no_override)
    try:
        body = TestClient(app).get("/auth/me").json()
    finally:
        app.dependency_overrides.pop(require_user, None)

    assert body["locale_effective"] == "en"


def test_patch_stores_the_choice_and_answers_like_me(api):
    client, _stored, written = api

    resp = client.patch("/auth/me", json={"locale": "ru"})

    assert resp.status_code == 200
    assert written == [("u1", "ru")]
    assert resp.json()["locale"] == "ru"
    assert resp.json()["locale_effective"] == "ru"


@pytest.mark.parametrize("payload", [{"locale": "auto"}, {"locale": ""}, {}])
def test_patch_clears_the_choice_back_to_the_account(api, payload):
    """Empty and "auto" are the same value: follow the account again."""
    client, stored, written = api
    stored["value"] = "ru"

    resp = client.patch("/auth/me", json=payload)

    assert resp.status_code == 200
    assert written == [("u1", None)]
    assert resp.json()["locale"] is None
    assert resp.json()["locale_effective"] == "uk"


def test_patch_normalizes_a_regional_tag(api):
    client, _stored, written = api

    client.patch("/auth/me", json={"locale": "en-US"})

    assert written == [("u1", "en")]


def test_patch_refuses_a_language_we_do_not_ship(api):
    client, _stored, written = api

    resp = client.patch("/auth/me", json={"locale": "de"})

    assert resp.status_code == 422
    assert written == []


def test_patch_reports_a_failed_write(api, monkeypatch):
    """A choice that cannot be stored must not be reported as saved."""
    client, _stored, _written = api

    async def _boom(_user_id, _value):
        raise RuntimeError("column is gone")

    monkeypatch.setattr(auth_routes, "set_locale_override", _boom)

    assert client.patch("/auth/me", json={"locale": "ru"}).status_code == 503
