"""Tests for cortex/hippo/tools/common.py."""

from __future__ import annotations

import json

import pytest

from cortex.hippo.tools.common import json_result, read_string_param


class TestJsonResult:
    def test_output_format(self):
        payload = {"key": "value", "count": 42}
        result = json_result(payload)

        assert "content" in result
        assert "details" in result
        assert result["details"] is payload

        content = result["content"]
        assert len(content) == 1
        assert content[0]["type"] == "text"
        assert json.loads(content[0]["text"]) == payload

    def test_indentation(self):
        result = json_result({"a": 1})
        text = result["content"][0]["text"]
        # Should be indented with 2 spaces
        assert "  " in text

    def test_none_payload(self):
        result = json_result(None)
        assert result["details"] is None
        assert result["content"][0]["text"] == "null"

    def test_list_payload(self):
        result = json_result([1, 2, 3])
        assert json.loads(result["content"][0]["text"]) == [1, 2, 3]


class TestReadStringParam:
    def test_basic_read(self):
        assert read_string_param({"key": "value"}, "key") == "value"

    def test_missing_optional(self):
        assert read_string_param({}, "key") is None

    def test_missing_required_raises(self):
        with pytest.raises(ValueError, match="key is required"):
            read_string_param({}, "key", required=True)

    def test_custom_label_in_error(self):
        with pytest.raises(ValueError, match="Pattern is required"):
            read_string_param({}, "key", required=True, label="Pattern")

    def test_trim_default(self):
        assert read_string_param({"k": "  hello  "}, "k") == "hello"

    def test_trim_disabled(self):
        assert read_string_param({"k": "  hello  "}, "k", trim=False) == "  hello  "

    def test_empty_string_not_allowed(self):
        assert read_string_param({"k": "   "}, "k") is None

    def test_empty_string_required_raises(self):
        with pytest.raises(ValueError, match="k is required"):
            read_string_param({"k": "   "}, "k", required=True)

    def test_empty_string_allowed(self):
        assert read_string_param({"k": ""}, "k", allow_empty=True) == ""

    def test_non_string_raises(self):
        with pytest.raises(ValueError, match="k must be a string"):
            read_string_param({"k": 123}, "k")

    def test_none_value_optional(self):
        assert read_string_param({"k": None}, "k") is None

    def test_none_value_required_raises(self):
        with pytest.raises(ValueError, match="k is required"):
            read_string_param({"k": None}, "k", required=True)
