"""Tests for lapis_spec.parser.schema_flattener."""

from lapis_spec.parser.schema_flattener import flatten_schema, flatten_schemas


class TestFlattenAllOf:
    def test_merge_properties(self):
        schema = {
            "allOf": [
                {
                    "type": "object",
                    "properties": {"a": {"type": "string"}},
                    "required": ["a"],
                },
                {
                    "type": "object",
                    "properties": {"b": {"type": "integer"}},
                    "required": ["b"],
                },
            ]
        }
        result = flatten_schema(schema)
        assert "allOf" not in result
        assert result["properties"]["a"]["type"] == "string"
        assert result["properties"]["b"]["type"] == "integer"
        assert set(result["required"]) == {"a", "b"}
        assert result["type"] == "object"

    def test_preserves_existing_properties(self):
        schema = {
            "type": "object",
            "properties": {"c": {"type": "boolean"}},
            "allOf": [
                {"properties": {"a": {"type": "string"}}},
            ],
        }
        result = flatten_schema(schema)
        assert "c" in result["properties"]
        assert "a" in result["properties"]

    def test_deduplicates_required(self):
        schema = {
            "allOf": [
                {"required": ["a", "b"]},
                {"required": ["b", "c"]},
            ]
        }
        result = flatten_schema(schema)
        assert result["required"] == ["a", "b", "c"]


class TestFlattenOneOf:
    def test_single_variant(self):
        schema = {
            "oneOf": [{"type": "string"}]
        }
        result = flatten_schema(schema)
        assert "oneOf" not in result
        assert result.get("type") == "string"

    def test_multiple_variants_preserved(self):
        schema = {
            "oneOf": [{"type": "string"}, {"type": "integer"}]
        }
        result = flatten_schema(schema)
        assert "oneOf" not in result

    def test_empty_one_of(self):
        schema = {"oneOf": []}
        result = flatten_schema(schema)
        assert "oneOf" not in result


class TestFlattenAnyOf:
    def test_single_variant(self):
        schema = {
            "anyOf": [{"type": "boolean"}]
        }
        result = flatten_schema(schema)
        assert "anyOf" not in result
        assert result.get("type") == "boolean"

    def test_multiple_variants(self):
        schema = {
            "anyOf": [{"type": "string"}, {"type": "null"}]
        }
        result = flatten_schema(schema)
        assert "anyOf" not in result


class TestFlattenSchemas:
    def test_walks_entire_document(self):
        doc = {
            "components": {
                "schemas": {
                    "Merged": {
                        "allOf": [
                            {"properties": {"x": {"type": "string"}}},
                            {"properties": {"y": {"type": "integer"}}},
                        ]
                    }
                }
            }
        }
        flatten_schemas(doc)
        merged = doc["components"]["schemas"]["Merged"]
        assert "allOf" not in merged
        assert "x" in merged["properties"]
        assert "y" in merged["properties"]

    def test_nested_all_of_in_array(self):
        schema = {
            "type": "array",
            "items": {
                "allOf": [
                    {"properties": {"a": {"type": "string"}}},
                ]
            },
        }
        result = flatten_schema(schema)
        assert "allOf" not in result["items"]
        assert "a" in result["items"]["properties"]
