"""Tests for app.utils.json_extractor — extract_json"""
import json

import pytest

from app.utils.json_extractor import extract_json


class TestExtractJsonPlainObject:
    """纯 JSON 对象"""

    def test_simple_object(self):
        text = '{"key": "value"}'
        result = extract_json(text)
        assert json.loads(result) == {"key": "value"}

    def test_nested_object(self):
        text = '{"a": {"b": [1, 2]}}'
        result = extract_json(text)
        assert json.loads(result) == {"a": {"b": [1, 2]}}


class TestExtractJsonMarkdownCodeBlock:
    """JSON 包裹在 markdown 代码块中"""

    def test_json_code_block(self):
        text = '```json\n{"key": "value"}\n```'
        result = extract_json(text)
        assert json.loads(result) == {"key": "value"}

    def test_plain_code_block(self):
        text = '```\n{"key": "value"}\n```'
        result = extract_json(text)
        assert json.loads(result) == {"key": "value"}

    def test_code_block_with_surrounding_text(self):
        text = 'Here is the result:\n```json\n{"key": "value"}\n```\nDone.'
        result = extract_json(text)
        assert json.loads(result) == {"key": "value"}


class TestExtractJsonArray:
    """JSON 数组"""

    def test_simple_array(self):
        text = "[1, 2, 3]"
        result = extract_json(text)
        assert json.loads(result) == [1, 2, 3]

    def test_array_in_code_block(self):
        text = "```json\n[1, 2, 3]\n```"
        result = extract_json(text)
        assert json.loads(result) == [1, 2, 3]

    def test_array_with_surrounding_text(self):
        text = "Result: [1, 2, 3] done"
        result = extract_json(text)
        assert json.loads(result) == [1, 2, 3]


class TestExtractJsonWithSurroundingText:
    """JSON 被周围文本包裹"""

    def test_object_with_surrounding_text(self):
        text = 'Here is the result: {"key": "value"} done'
        result = extract_json(text)
        assert json.loads(result) == {"key": "value"}

    def test_nested_with_surrounding_text(self):
        text = 'Output: {"a": {"b": [1, 2]}} end'
        result = extract_json(text)
        assert json.loads(result) == {"a": {"b": [1, 2]}}


class TestExtractJsonInvalidInput:
    """无效输入应抛出 ValueError"""

    def test_no_json_at_all(self):
        with pytest.raises(ValueError, match="无法从响应中提取JSON"):
            extract_json("This is just plain text with no JSON")

    def test_empty_string(self):
        with pytest.raises(ValueError, match="无法从响应中提取JSON"):
            extract_json("")

    def test_unclosed_brace(self):
        with pytest.raises(ValueError, match="无法从响应中提取JSON"):
            extract_json('{"key": "value"')
