"""华为审核开关:admin 读写 + 客户端公开端点 + 审计 + 空库回退。

背景:华为应用市场审核要求新手引导的「快速设置」权限步必须可被用户关闭。开关切到 review 后
客户端(仅华为 ROM)在该步左上角显示退出按钮。默认 default = 上线至今的现状(不可关闭)。

autouse 清理每个用例后清空 app_config,避免污染其他文件里假设默认值的用例(同 test_admin_config)。
"""
from __future__ import annotations

from collections.abc import Iterator

import pytest
from fastapi.testclient import TestClient
from sqlalchemy import delete, select

from app.admin.main import admin_app
from app.admin.repositories import admin_user as admin_repo
from app.db.session import SessionLocal
from app.models.admin import AdminAuditLog
from app.models.app_config import AppConfig


@pytest.fixture()
def admin_client() -> TestClient:
    return TestClient(admin_app)


@pytest.fixture()
def token() -> str:
    db = SessionLocal()
    try:
        if admin_repo.get_by_username(db, "hw_admin") is None:
            admin_repo.create_admin(
                db, username="hw_admin", password="hwpass123", role="super_admin"
            )
    finally:
        db.close()
    c = TestClient(admin_app)
    return c.post(
        "/admin/api/auth/login", json={"username": "hw_admin", "password": "hwpass123"}
    ).json()["access_token"]


@pytest.fixture(autouse=True)
def _clean_config() -> Iterator[None]:
    yield
    db = SessionLocal()
    try:
        db.execute(delete(AppConfig))
        # 审计行同样要清:同库跨用例累积会让 test_switch_writes_audit 数到前面用例写的行
        # (按 action 限定,不碰其他模块可能已写入的审计)。
        db.execute(delete(AdminAuditLog).where(AdminAuditLog.action == "huawei_review.set"))
        db.commit()
    finally:
        db.close()


def _auth(t: str) -> dict:
    return {"Authorization": f"Bearer {t}"}


def test_public_default_not_closable(client: TestClient) -> None:
    """空库(从未切过)→ 客户端拿到 default / 不可关闭 = 维持现状;且不需要鉴权。"""
    r = client.get("/api/v1/platform/huawei-review")
    assert r.status_code == 200, r.text
    assert r.json() == {"mode": "default", "onboarding_closable": False}


def test_admin_get_default(admin_client: TestClient, token: str) -> None:
    r = admin_client.get("/admin/api/huawei-review", headers=_auth(token))
    assert r.status_code == 200, r.text
    body = r.json()
    assert body["mode"] == "default"
    assert body["updated_at"] is None  # 从未切过


def test_switch_to_review_takes_effect(
    admin_client: TestClient, client: TestClient, token: str
) -> None:
    """admin 切 review → 公开端点立刻下发可关闭(跨进程/跨 app 一致,因为落在 DB 而非内存)。"""
    r = admin_client.patch(
        "/admin/api/huawei-review", json={"mode": "review"}, headers=_auth(token)
    )
    assert r.status_code == 200, r.text
    assert r.json()["mode"] == "review"
    assert r.json()["updated_at"] is not None

    pub = client.get("/api/v1/platform/huawei-review").json()
    assert pub == {"mode": "review", "onboarding_closable": True}

    # 切回 default → 客户端恢复不可关闭(审核过了要能一键收回)
    admin_client.patch(
        "/admin/api/huawei-review", json={"mode": "default"}, headers=_auth(token)
    )
    assert client.get("/api/v1/platform/huawei-review").json()["onboarding_closable"] is False


def test_switch_writes_audit(admin_client: TestClient, token: str) -> None:
    admin_client.patch(
        "/admin/api/huawei-review", json={"mode": "review"}, headers=_auth(token)
    )
    db = SessionLocal()
    try:
        logs = db.execute(
            select(AdminAuditLog).where(AdminAuditLog.action == "huawei_review.set")
        ).scalars().all()
        assert len(logs) == 1
        assert logs[0].detail == {"before": "default", "after": "review"}
    finally:
        db.close()


def test_invalid_mode_rejected(admin_client: TestClient, token: str) -> None:
    """mode 是 Literal,非法值由 FastAPI 校验挡在 422(不会落库)。"""
    r = admin_client.patch(
        "/admin/api/huawei-review", json={"mode": "nope"}, headers=_auth(token)
    )
    assert r.status_code == 422, r.text
    db = SessionLocal()
    try:
        assert db.get(AppConfig, "huawei_review") is None
    finally:
        db.close()


def test_requires_admin_auth(admin_client: TestClient) -> None:
    assert admin_client.get("/admin/api/huawei-review").status_code == 401
    assert admin_client.patch(
        "/admin/api/huawei-review", json={"mode": "review"}
    ).status_code == 401
