"""
控制 API（approve / reject / respond）+ Stats + Messages 测试。
"""

from __future__ import annotations

import httpx
import pytest
import respx

from cmdc import CMDC, BadRequestError


BASE_URL = "http://localhost:4000"
API_KEY = "sk-test"


def make_session():
    with respx.mock:
        respx.post(f"{BASE_URL}/v1/sessions").mock(
            return_value=httpx.Response(
                201, json={"sessionId": "ctrl-sess", "status": "created"}
            )
        )
        client = CMDC(base_url=BASE_URL, api_key=API_KEY)
        return client, client.create_session(model="deepseek:deepseek-chat")


class TestControlAPI:
    @respx.mock
    def test_approve(self) -> None:
        respx.post(f"{BASE_URL}/v1/sessions").mock(
            return_value=httpx.Response(
                201, json={"sessionId": "ctrl-sess", "status": "created"}
            )
        )
        route = respx.post(f"{BASE_URL}/v1/sessions/ctrl-sess/approve").mock(
            return_value=httpx.Response(
                200,
                json={"ok": True, "action": "approve", "approvalId": "apr_001"},
            )
        )

        client = CMDC(base_url=BASE_URL, api_key=API_KEY)
        session = client.create_session(model="deepseek:deepseek-chat")
        session.approve("apr_001")

        assert route.called
        import json
        body = json.loads(route.calls[0].request.content)
        assert body["approvalId"] == "apr_001"

    @respx.mock
    def test_reject(self) -> None:
        respx.post(f"{BASE_URL}/v1/sessions").mock(
            return_value=httpx.Response(
                201, json={"sessionId": "ctrl-sess", "status": "created"}
            )
        )
        route = respx.post(f"{BASE_URL}/v1/sessions/ctrl-sess/reject").mock(
            return_value=httpx.Response(
                200,
                json={"ok": True, "action": "reject", "approvalId": "apr_001"},
            )
        )

        client = CMDC(base_url=BASE_URL, api_key=API_KEY)
        session = client.create_session(model="deepseek:deepseek-chat")
        session.reject("apr_001")

        assert route.called

    @respx.mock
    def test_respond(self) -> None:
        respx.post(f"{BASE_URL}/v1/sessions").mock(
            return_value=httpx.Response(
                201, json={"sessionId": "ctrl-sess", "status": "created"}
            )
        )
        route = respx.post(f"{BASE_URL}/v1/sessions/ctrl-sess/respond").mock(
            return_value=httpx.Response(
                200,
                json={"ok": True, "action": "respond", "ref": "ask_001"},
            )
        )

        client = CMDC(base_url=BASE_URL, api_key=API_KEY)
        session = client.create_session(model="deepseek:deepseek-chat")
        session.respond("ask_001", "快速排序")

        assert route.called
        import json
        body = json.loads(route.calls[0].request.content)
        assert body["ref"] == "ask_001"
        assert body["response"] == "快速排序"


class TestStatsAndMessages:
    @respx.mock
    def test_get_stats(self) -> None:
        respx.post(f"{BASE_URL}/v1/sessions").mock(
            return_value=httpx.Response(
                201, json={"sessionId": "stats-sess", "status": "created"}
            )
        )
        respx.get(f"{BASE_URL}/v1/sessions/stats-sess/stats").mock(
            return_value=httpx.Response(
                200,
                json={
                    "sessionId": "stats-sess",
                    "turns": 5,
                    "totalTokens": 2500,
                    "costUsd": 0.0015,
                    "promptCount": 3,
                    "tokenUsage": {
                        "promptTokens": 2000,
                        "completionTokens": 500,
                        "totalTokens": 2500,
                    },
                },
            )
        )

        client = CMDC(base_url=BASE_URL, api_key=API_KEY)
        session = client.create_session(model="deepseek:deepseek-chat")
        stats = session.get_stats()

        assert stats.session_id == "stats-sess"
        assert stats.turns == 5
        assert stats.total_tokens == 2500
        assert stats.cost_usd == pytest.approx(0.0015)
        assert stats.token_usage.prompt_tokens == 2000

    @respx.mock
    def test_get_messages(self) -> None:
        respx.post(f"{BASE_URL}/v1/sessions").mock(
            return_value=httpx.Response(
                201, json={"sessionId": "msg-sess", "status": "created"}
            )
        )
        respx.get(f"{BASE_URL}/v1/sessions/msg-sess/messages").mock(
            return_value=httpx.Response(
                200,
                json={
                    "sessionId": "msg-sess",
                    "messages": [
                        {"role": "user", "content": "你好"},
                        {"role": "assistant", "content": "你好！有什么可以帮你？"},
                    ],
                },
            )
        )

        client = CMDC(base_url=BASE_URL, api_key=API_KEY)
        session = client.create_session(model="deepseek:deepseek-chat")
        messages = session.get_messages()

        assert len(messages) == 2
        assert messages[0].role == "user"
        assert messages[0].content == "你好"
        assert messages[1].role == "assistant"
