"""比价战绩里程碑测试:进度随成功比价数解锁 / 逐档领奖发金币 / 幂等 / 边界。

复用比价记录上报接口造成功记录(每条 trace 一次成功比价),再验里程碑。
"""
from __future__ import annotations

from app.core.rewards import RECORD_MILESTONES


def _login(client, phone: str) -> str:
    client.post("/api/v1/auth/sms/send", json={"phone": phone})
    r = client.post("/api/v1/auth/sms/login", json={"phone": phone, "code": "123456"})
    assert r.status_code == 200, r.text
    return r.json()["access_token"]


def _auth(token: str) -> dict[str, str]:
    return {"Authorization": f"Bearer {token}"}


def _report_success(client, token: str, trace_id: str) -> None:
    """上报一条成功比价(有非源有效价 → status 派生 success)。"""
    payload = {
        "trace_id": trace_id,
        "business_type": "food",
        "store_name": "测试店",
        "source_platform_id": "taobao_flash",
        "source_price": 30.0,
        "comparison_results": [
            {"platform_id": "meituan", "platform_name": "美团", "price": 25.0,
             "is_source": False, "rank": 1},
            {"platform_id": "taobao_flash", "platform_name": "淘宝闪购", "price": 30.0,
             "is_source": True, "rank": 2},
        ],
    }
    r = client.post("/api/v1/compare/record", json=payload, headers=_auth(token))
    assert r.status_code == 200, r.text


def _report_failed(client, token: str, trace_id: str) -> None:
    """上报一条失败比价(只有源 → status 派生 failed,不计入解锁)。"""
    payload = {
        "trace_id": trace_id,
        "business_type": "food",
        "comparison_results": [
            {"platform_id": "taobao_flash", "platform_name": "淘宝闪购", "price": 30.0,
             "is_source": True, "rank": 1},
        ],
    }
    r = client.post("/api/v1/compare/record", json=payload, headers=_auth(token))
    assert r.status_code == 200, r.text


def test_status_empty(client) -> None:
    """没比价过:成功数 0,所有档 locked,无可领。"""
    token = _login(client, "13800003001")
    r = client.get("/api/v1/compare/milestones", headers=_auth(token))
    assert r.status_code == 200, r.text
    d = r.json()
    assert d["success_count"] == 0
    assert d["claimable_count"] == 0
    assert len(d["milestones"]) == len(RECORD_MILESTONES)
    assert all(m["state"] == "locked" for m in d["milestones"])
    # 第 1 档金币对齐配置
    assert d["milestones"][0]["coin"] == RECORD_MILESTONES[0]
    assert d["milestones"][0]["milestone"] == 1


def test_unlock_progresses_with_success(client) -> None:
    """成功比价 2 次:前 2 档 active 可领,其余 locked。失败记录不计入。"""
    token = _login(client, "13800003002")
    _report_success(client, token, "s-1")
    _report_success(client, token, "s-2")
    _report_failed(client, token, "f-1")  # 失败不计

    d = client.get("/api/v1/compare/milestones", headers=_auth(token)).json()
    assert d["success_count"] == 2
    assert d["claimable_count"] == 2
    states = [m["state"] for m in d["milestones"]]
    assert states[0] == "active"
    assert states[1] == "active"
    assert states[2] == "locked"


def test_claim_marks_claimed_without_coin(client) -> None:
    """领第 1 档:暂不真发金币(产品定,后续删该功能),余额不变,但该档变 claimed。"""
    token = _login(client, "13800003003")
    _report_success(client, token, "s-1")

    bal_before = client.get("/api/v1/wallet/account", headers=_auth(token)).json()["coin_balance"]

    r = client.post("/api/v1/compare/milestones/1/claim", headers=_auth(token))
    assert r.status_code == 200, r.text
    res = r.json()
    assert res["milestone"] == 1
    assert res["coin_awarded"] == 0          # 不再发金币
    assert res["coin_balance"] == bal_before  # 余额不变

    d = client.get("/api/v1/compare/milestones", headers=_auth(token)).json()
    assert d["milestones"][0]["state"] == "claimed"
    assert d["claimable_count"] == 0  # 第 1 档领掉了,成功数 1 没解锁第 2 档


def test_claim_idempotent_409(client) -> None:
    """同档重复领 → 409,且不重复发金币。"""
    token = _login(client, "13800003004")
    _report_success(client, token, "s-1")
    assert client.post("/api/v1/compare/milestones/1/claim", headers=_auth(token)).status_code == 200
    bal = client.get("/api/v1/wallet/account", headers=_auth(token)).json()["coin_balance"]

    r = client.post("/api/v1/compare/milestones/1/claim", headers=_auth(token))
    assert r.status_code == 409
    bal2 = client.get("/api/v1/wallet/account", headers=_auth(token)).json()["coin_balance"]
    assert bal2 == bal  # 没重复发


def test_claim_locked_409(client) -> None:
    """领还没解锁的档(成功数不够)→ 409 locked。"""
    token = _login(client, "13800003005")
    _report_success(client, token, "s-1")  # 只解锁第 1 档
    r = client.post("/api/v1/compare/milestones/2/claim", headers=_auth(token))
    assert r.status_code == 409


def test_claim_unknown_milestone_404(client) -> None:
    """档位越界 → 404。"""
    token = _login(client, "13800003006")
    assert client.post("/api/v1/compare/milestones/0/claim", headers=_auth(token)).status_code == 404
    big = len(RECORD_MILESTONES) + 1
    assert client.post(f"/api/v1/compare/milestones/{big}/claim", headers=_auth(token)).status_code == 404


def test_requires_auth(client) -> None:
    """不带 token → 401。"""
    assert client.get("/api/v1/compare/milestones").status_code == 401
    assert client.post("/api/v1/compare/milestones/1/claim").status_code == 401
