# backend/tests/test_settings.py — 설정 라우터(시스템 스냅샷 + LLM 편집/적용/테스트) + 프로필/토큰
from app import runtime_config
from app.llm.provider import get_provider


def test_system_snapshot_readonly(client):
    d = client.get("/api/settings/system").json()
    assert d["env"] == "dev"
    assert d["auth_enabled"] is False  # 데모 기본 off
    assert d["database"] == "sqlite"
    assert set(d["connector_modes"]) == {
        "calendar",
        "mail",
        "chat",
        "finance",
        "health",
        "knowledge",
    }
    # 기본은 전부 mock
    assert all(v == "mock" for v in d["connector_modes"].values())


def test_llm_config_defaults_match_env(client):
    d = client.get("/api/settings/llm").json()
    assert d["provider"] in ("auto", "ollama", "heuristic")
    assert d["overridden"] is False  # 오버레이 없음 → env 기본
    assert "auto" in d["provider_options"]
    # 보조 프로바이더 노출
    assert "embed_provider" in d and "stt_provider" in d


def test_llm_update_persists_and_applies(client):
    # heuristic 으로 저장 → 영속 + 런타임 반영
    r = client.put("/api/settings/llm", json={"provider": "heuristic", "model": "my-model"})
    assert r.status_code == 200
    body = r.json()
    assert body["provider"] == "heuristic"
    assert body["model"] == "my-model"
    assert body["overridden"] is True

    # 다시 GET 해도 유지(영속)
    again = client.get("/api/settings/llm").json()
    assert again["provider"] == "heuristic" and again["model"] == "my-model"

    # 런타임 오버레이가 실제 provider 선택에 반영되는가(force 없이)
    assert runtime_config.effective_llm().provider == "heuristic"
    assert get_provider().name == "heuristic"


def test_llm_update_reset_to_default(client):
    client.put("/api/settings/llm", json={"provider": "ollama"})
    assert client.get("/api/settings/llm").json()["provider"] == "ollama"
    # 빈 문자열 → 기본으로 되돌리기
    r = client.put("/api/settings/llm", json={"provider": ""})
    assert r.status_code == 200
    assert r.json()["overridden"] is False
    assert runtime_config.snapshot() == {}


def test_llm_update_rejects_bad_provider(client):
    r = client.put("/api/settings/llm", json={"provider": "gpt5"})
    assert r.status_code == 400


def test_llm_test_heuristic_reachable(client):
    r = client.post("/api/settings/llm/test", json={"provider": "heuristic"})
    assert r.status_code == 200
    d = r.json()
    assert d["reachable"] is True and d["provider"] == "heuristic"


def test_profile_update(client):
    r = client.patch("/api/me", json={"name": "지우님", "role": "프로덕트 리드"})
    assert r.status_code == 200
    d = r.json()
    assert d["name"] == "지우님"
    assert d["initial"] == "지"
    assert d["role"] == "프로덕트 리드"
    # 영속 확인
    assert client.get("/api/me").json()["role"] == "프로덕트 리드"


def test_api_tokens_create_list_revoke(client):
    # 처음엔 토큰 없음
    assert client.get("/api/me/tokens").json() == []
    # 생성 → 평문 1회 노출
    created = client.post("/api/me/tokens", params={"name": "CLI"}).json()
    assert created["token"] and created["name"] == "CLI"
    tid = created["id"]
    # 목록(평문 미포함)
    rows = client.get("/api/me/tokens").json()
    assert len(rows) == 1 and rows[0]["id"] == tid and "token" not in rows[0]
    assert rows[0]["revoked"] is False
    # 폐기
    assert client.delete(f"/api/me/tokens/{tid}").status_code == 200
    assert client.get("/api/me/tokens").json()[0]["revoked"] is True
