import httpx
import pytest

from chatiss_open_sdk import OpenAPIClient, SDKConfig
from chatiss_open_sdk.exceptions import NetworkError
from chatiss_open_sdk.types import TongueCreateRequest, TongueCreateResult


def _make_config() -> SDKConfig:
    return SDKConfig(
        access_key_id="test-ak",
        access_key_secret="test-sk",
    )


def test_get_jwt_token_fail_returns_api_response(monkeypatch):
    client = OpenAPIClient(_make_config())

    def fake_request(*args, **kwargs):
        return {"status": "FAIL", "code": 1001, "msg": "invalid ak/sk", "result": None}

    monkeypatch.setattr(client, "_request", fake_request)
    try:
        response = client.get_jwt_token()
    finally:
        client.close()

    assert response.status == "FAIL"
    assert response.code == 1001
    assert response.msg == "invalid ak/sk"
    assert response.result is None


def test_sync_client_supports_context_manager():
    with OpenAPIClient(_make_config()) as client:
        assert client._http.is_closed is False
    assert client._http.is_closed is True


def test_stream_sse_maps_request_error_to_network_error(monkeypatch):
    client = OpenAPIClient(_make_config())

    def fake_connect_sse(*args, **kwargs):
        request = httpx.Request("POST", "https://devopenapi.chatiss.com/tongue/create/")
        raise httpx.ConnectError("boom", request=request)

    monkeypatch.setattr("chatiss_open_sdk.core.base.connect_sse", fake_connect_sse)

    with pytest.raises(NetworkError):
        list(client._stream_sse("POST", "/tongue/create/", json_body={}, auth=False))

    client.close()


def test_word_article_detail_success(monkeypatch):
    client = OpenAPIClient(_make_config())

    def fake_request(method, endpoint, **kwargs):
        assert method == "GET"
        assert endpoint == "/article/word_article_detail/"
        assert kwargs["params"] == {"article_id": "632278c7-5e6c-487a-b8b3-ec91fc42840f"}
        return {
            "status": "SUCCESS",
            "result": {
                "id": "632278c7-5e6c-487a-b8b3-ec91fc42840f",
                "paragraphs": [
                    {"title": "section-1", "content": "content-1"},
                    {"title": "section-2", "content": "content-2"},
                ],
            },
        }

    monkeypatch.setattr(client, "_request", fake_request)
    try:
        response = client.word_article_detail("632278c7-5e6c-487a-b8b3-ec91fc42840f")
    finally:
        client.close()

    assert response.status == "SUCCESS"
    assert response.result is not None
    assert response.result.id == "632278c7-5e6c-487a-b8b3-ec91fc42840f"
    assert response.result.paragraphs is not None
    assert len(response.result.paragraphs) == 2
    assert response.result.paragraphs[0].title == "section-1"


def test_tongue_create_success_event_is_typed(monkeypatch):
    client = OpenAPIClient(_make_config())

    def fake_stream(*args, **kwargs):
        yield {
            "event": "message",
            "data": {
                "status": "SUCCESS",
                "result": {
                    "id": "tongue-id",
                    "is_valid": True,
                    "nmpa_tongue_result": [
                        {
                            "zone": "all",
                            "words": [
                                {"article_id": None, "title": "word-1"},
                            ],
                        }
                    ],
                    "nmpa_asking_result": [
                        {
                            "category": "category-1",
                            "words": [
                                {"article_id": "article-1", "title": "word-2"},
                            ],
                        }
                    ],
                    "tongue_data": [
                        {
                            "indicators": [
                                {
                                    "name": "indicator-1",
                                    "value": 0.221,
                                    "status": "+",
                                    "status_note": "note-1",
                                }
                            ],
                            "zone": "zone-1",
                            "viscera": "viscera-1",
                        }
                    ],
                    "invalid_code": None,
                    "invalid_reason": None,
                },
            },
        }

    monkeypatch.setattr(client, "_stream_sse", fake_stream)

    req = TongueCreateRequest(
        original_img="https://example.com/a.png",
        skin_img="https://example.com/b.png",
        gender=1,
        birthday="1990-01-01",
        use_flash=False,
    )

    try:
        events = list(client.tongue_create(req))
    finally:
        client.close()

    assert len(events) == 1
    assert isinstance(events[0].data.result, TongueCreateResult)
    assert events[0].data.result is not None
    assert events[0].data.result.is_valid is True
    assert events[0].data.result.nmpa_tongue_result is not None
    assert events[0].data.result.nmpa_tongue_result[0].words is not None
    assert events[0].data.result.nmpa_tongue_result[0].words[0].article_id is None
    assert events[0].data.result.tongue_data is not None
    assert events[0].data.result.tongue_data[0].indicators is not None
    assert events[0].data.result.tongue_data[0].indicators[0].value == 0.221


def test_tongue_create_success_event_allows_nullable_fields(monkeypatch):
    client = OpenAPIClient(_make_config())

    def fake_stream(*args, **kwargs):
        yield {
            "event": "message",
            "data": {
                "status": "SUCCESS",
                "result": {
                    "id": "tongue-id",
                    "is_valid": True,
                    "nmpa_tongue_result": [
                        {
                            "zone": "all",
                            "words": [],
                        }
                    ],
                    "nmpa_asking_result": [
                        {
                            "category": "category-1",
                            "words": [],
                        }
                    ],
                    "tongue_data": [
                        {
                            "indicators": [
                                {
                                    "name": "indicator-1",
                                    "value": 0.0,
                                    "status": "",
                                    "status_note": "",
                                }
                            ],
                            "zone": "zone-1",
                            "viscera": "viscera-1",
                        }
                    ],
                    "invalid_code": None,
                    "invalid_reason": None,
                },
            },
        }

    monkeypatch.setattr(client, "_stream_sse", fake_stream)

    req = TongueCreateRequest(
        original_img="https://example.com/a.png",
        skin_img="https://example.com/b.png",
        gender=1,
        birthday="1990-01-01",
        use_flash=False,
    )

    try:
        events = list(client.tongue_create(req))
    finally:
        client.close()

    assert len(events) == 1
    assert events[0].data.result is not None
    assert events[0].data.result.id == "tongue-id"
    assert events[0].data.result.nmpa_tongue_result is not None
    assert events[0].data.result.nmpa_tongue_result[0].words == []
    assert events[0].data.result.nmpa_asking_result is not None
    assert events[0].data.result.nmpa_asking_result[0].words == []
    assert events[0].data.result.invalid_code is None
    assert events[0].data.result.invalid_reason is None
