"""FEAT-034 mail.send 前置实名闸门集成测试。

conftest autouse `_bypass_realname_by_default` 默认 monkeypatch 掉闸门，
本文件**恢复真实 assert_user_verified** 来测闸门真实行为。
"""

from __future__ import annotations

import pytest

from xiangqin import auth, mail, realname


# ─── fixture：恢复真实闸门（覆盖 conftest 的 bypass） ───


@pytest.fixture
def enforce_realname(monkeypatch):
    """恢复真实 realname.assert_user_verified（覆盖 conftest bypass）。"""
    # 重新 import 拿到原 function object（非 monkeypatch 过的）
    import importlib

    realname_mod = importlib.reload(realname)
    monkeypatch.setattr(
        realname,
        "assert_user_verified",
        realname_mod.assert_user_verified,
    )


def _register(phone: str) -> str:
    r = auth.register(phone)
    return auth.verify(r.request_id, "123456").user_id


# ─── 发信闸门 ──────────────────────────────────────────


def test_unverified_cannot_send(enforce_realname):
    a = _register("13800001111")
    b = _register("13800002222")
    with pytest.raises(mail.MailError) as e:
        mail.send(a, b, "hi")
    assert e.value.code == "not_verified"


def test_verified_can_send(enforce_realname, monkeypatch):
    monkeypatch.setenv("XIANGQIN_TEST_CERT_IDS", "110101199001011237")
    a = _register("13800001111")
    b = _register("13800002222")
    # A 实名
    realname.verify(a, "张三", "110101199001011237")
    # A 发信应成功（B 未实名也不拦，决策点 #4）
    msg = mail.send(a, b, "hi from verified A")
    assert msg.delivery_status == "delivered"


def test_recipient_unverified_not_blocking(enforce_realname, monkeypatch):
    """决策点 #4：发给未实名用户不拦。"""
    monkeypatch.setenv("XIANGQIN_TEST_CERT_IDS", "110101199001011237")
    a = _register("13800001111")
    b = _register("13800002222")
    realname.verify(a, "张三", "110101199001011237")
    # B 未实名，A 仍能发给 B
    msg = mail.send(a, b, "hi")
    assert msg.delivery_status == "delivered"


def test_verified_error_propagates_as_mail_error(enforce_realname):
    """realname.RealnameError(not_verified) → MailError(not_verified)。"""
    a = _register("13800001111")
    b = _register("13800002222")
    try:
        mail.send(a, b, "hi")
    except mail.MailError as e:
        assert e.code == "not_verified"
        assert "实名" in str(e)
    else:
        pytest.fail("未抛 MailError")


# ─── API endpoint (FEAT-031') ──────────────────────────


@pytest.fixture
def client(monkeypatch):
    monkeypatch.setenv("XIANGQIN_TEST_CERT_IDS", "110101199001011237")
    # endpoint 测试需要真实 assert_user_verified（否则闸门 bypass 看不到 403）
    import importlib

    realname_mod = importlib.reload(realname)
    monkeypatch.setattr(realname, "assert_user_verified", realname_mod.assert_user_verified)

    from fastapi.testclient import TestClient

    from xiangqin.app import app

    return TestClient(app)


def test_verify_id_endpoint_success(client):
    # 注册 + 拿 token
    r = client.post("/auth/register", json={"phone": "13900000001"})
    req = r.json()["request_id"]
    r = client.post("/auth/verify", json={"request_id": req, "code": "123456"})
    token = r.json()["session_token"]

    r = client.post(
        "/auth/verify-id",
        headers={"Authorization": f"Bearer {token}"},
        json={"legal_name": "张三", "cert_id": "110101199001011237"},
    )
    assert r.status_code == 200
    data = r.json()
    assert data["verified"] is True
    assert data["status"] == "passed"


def test_verify_id_endpoint_requires_auth(client):
    r = client.post(
        "/auth/verify-id",
        json={"legal_name": "张三", "cert_id": "110101199001011237"},
    )
    assert r.status_code == 401


def test_verify_id_endpoint_bad_cert_id(client):
    r = client.post("/auth/register", json={"phone": "13900000001"})
    req = r.json()["request_id"]
    token = client.post("/auth/verify", json={"request_id": req, "code": "123456"}).json()[
        "session_token"
    ]
    # 长度不够（<18）触发 pydantic 422
    r = client.post(
        "/auth/verify-id",
        headers={"Authorization": f"Bearer {token}"},
        json={"legal_name": "张三", "cert_id": "123"},
    )
    assert r.status_code == 422


def test_send_after_verify_id_works_end_to_end(client):
    """端到端：注册 A → 实名 → 注册 B → A 给 B 发信成功。"""
    # A 注册
    r = client.post("/auth/register", json={"phone": "13900000001"})
    ta = client.post(
        "/auth/verify",
        json={"request_id": r.json()["request_id"], "code": "123456"},
    ).json()["session_token"]
    # A 实名
    r = client.post(
        "/auth/verify-id",
        headers={"Authorization": f"Bearer {ta}"},
        json={"legal_name": "张三", "cert_id": "110101199001011237"},
    )
    assert r.json()["verified"]
    # B 注册
    r = client.post("/auth/register", json={"phone": "13900000002"})
    tb = client.post(
        "/auth/verify",
        json={"request_id": r.json()["request_id"], "code": "123456"},
    ).json()["session_token"]
    uid_b = client.get("/auth/me", headers={"Authorization": f"Bearer {tb}"}).json()["user_id"]
    # A 发信
    r = client.post(
        "/dm/send",
        headers={"Authorization": f"Bearer {ta}"},
        json={"to_user_id": uid_b, "body": "hi from verified A"},
    )
    assert r.status_code == 200
