"""多比比新增端点的冒烟测试。LLM 调用被 monkeypatch 成固定 JSON,避免真打智谱。"""
from __future__ import annotations

from unittest.mock import patch

from fastapi.testclient import TestClient

from app.main import app

client = TestClient(app)

ARENA_JSON = (
    '{"title":"iPhone 15 Pro 256GB","typical_price":8299.0,'
    '"quotes":[{"platform":"淘宝","price":8099.0,"note":""},'
    '{"platform":"京东","price":8299.0,"note":"自营"},'
    '{"platform":"拼多多","price":7888.0,"note":"百亿补贴"},'
    '{"platform":"抖音","price":8190.0,"note":""}]}'
)

WORTH_JSON = (
    '{"score":78,"verdict":"buy","headline":"现在入手划算",'
    '"reasons":["低于市场常见价约 2%","距下次大促还有一段时间"],'
    '"typical_price":8299.0,"best_time":"现在就合适"}'
)


def test_arena_quote_basic() -> None:
    with patch("app.api.arena.chat", return_value=ARENA_JSON):
        r = client.post("/api/v1/arena-quote", json={"title": "iPhone 15 Pro 256GB"})
    assert r.status_code == 200, r.text
    body = r.json()
    assert body["typical_price"] > 0
    assert len(body["quotes"]) == 4
    assert body["lowest_platform"] == "拼多多"  # 7888 最低


def test_arena_quote_synthesizes_missing_platforms() -> None:
    """LLM 只给 1 个平台,其余平台应被确定性合成,保证每行有值。"""
    only_one = '{"title":"x","typical_price":100.0,"quotes":[{"platform":"淘宝","price":95.0}]}'
    with patch("app.api.arena.chat", return_value=only_one):
        r = client.post(
            "/api/v1/arena-quote",
            json={"title": "x", "platforms": ["淘宝", "京东", "拼多多"]},
        )
    assert r.status_code == 200, r.text
    quotes = r.json()["quotes"]
    assert len(quotes) == 3
    assert {q["platform"] for q in quotes} == {"淘宝", "京东", "拼多多"}


def test_arena_quote_empty_title() -> None:
    r = client.post("/api/v1/arena-quote", json={"title": "   "})
    assert r.status_code == 422


def test_worth_buy_basic() -> None:
    with patch("app.api.worth_buy.chat", return_value=WORTH_JSON):
        r = client.post(
            "/api/v1/worth-buy",
            json={"title": "iPhone 15 Pro 256GB", "price": 8099.0},
        )
    assert r.status_code == 200, r.text
    body = r.json()
    assert 0 <= body["score"] <= 100
    assert body["verdict"] in {"buy", "wait", "neutral"}
    assert isinstance(body["reasons"], list) and body["reasons"]


def test_worth_buy_fallback_on_garbage() -> None:
    """LLM 返回非 JSON 垃圾时,接口仍给中性结论而非 5xx。"""
    with patch("app.api.worth_buy.chat", return_value="不是 JSON 的废话"):
        r = client.post("/api/v1/worth-buy", json={"title": "x", "price": 50.0})
    assert r.status_code == 200, r.text
    body = r.json()
    assert body["typical_price"] > 0
    assert body["verdict"] in {"buy", "wait", "neutral"}


def test_worth_buy_invalid_price() -> None:
    r = client.post("/api/v1/worth-buy", json={"title": "x", "price": 0})
    assert r.status_code == 422


def test_parse_ocr_boots_and_works() -> None:
    """parse-ocr 端点存在(修复了缺失 import),mock 延迟被关掉后能正常返回。"""
    async def _instant(_seconds):
        return None

    with patch("app.mock_extractor.asyncio.sleep", _instant):
        r = client.post(
            "/api/v1/parse-ocr",
            json={"ocr_text": "iPhone 15 Pro Max 256GB ¥8099 京东自营", "clusters": []},
        )
    assert r.status_code == 200, r.text
    assert r.json()["price"] > 0
