"""Tests for lapis_spec.sections.types."""

from lapis_spec.models.lapis import LapisEnumType, LapisObjectType
from lapis_spec.sections.types import convert_types


class TestConvertTypes:
    def test_enum_type(self):
        doc = {
            "components": {
                "schemas": {
                    "Status": {
                        "type": "string",
                        "enum": ["active", "inactive", "pending"],
                    }
                }
            },
            "paths": {
                "/items": {
                    "get": {
                        "responses": {
                            "200": {
                                "content": {
                                    "application/json": {
                                        "schema": {
                                            "$ref": "#/components/schemas/Status"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            },
        }
        types, name_map = convert_types(doc)
        enum_types = [t for t in types if isinstance(t, LapisEnumType)]
        assert len(enum_types) == 1
        assert enum_types[0].name == "Status"
        assert enum_types[0].values == ["active", "inactive", "pending"]
        assert "Status" in name_map

    def test_object_type(self):
        doc = {
            "components": {
                "schemas": {
                    "Address": {
                        "type": "object",
                        "required": ["street", "city"],
                        "properties": {
                            "street": {"type": "string"},
                            "city": {"type": "string"},
                            "zip": {"type": "string"},
                            "country": {"type": "string", "default": "US"},
                        },
                    }
                }
            },
            "paths": {
                "/addr": {
                    "get": {
                        "responses": {
                            "200": {
                                "content": {
                                    "application/json": {
                                        "schema": {"$ref": "#/components/schemas/Address"}
                                    }
                                }
                            }
                        }
                    },
                    "post": {
                        "requestBody": {
                            "content": {
                                "application/json": {
                                    "schema": {"$ref": "#/components/schemas/Address"}
                                }
                            }
                        },
                        "responses": {"200": {"description": "ok"}},
                    },
                }
            },
        }
        types, name_map = convert_types(doc)
        obj_types = [t for t in types if isinstance(t, LapisObjectType)]
        assert len(obj_types) == 1
        addr = obj_types[0]
        assert addr.name == "Address"
        field_names = [f.name for f in addr.fields]
        assert "street" in field_names
        assert "city" in field_names

        street = next(f for f in addr.fields if f.name == "street")
        assert not street.optional

        zip_field = next(f for f in addr.fields if f.name == "zip")
        assert zip_field.optional

        country = next(f for f in addr.fields if f.name == "country")
        assert country.default == '"US"'

    def test_field_since_annotation(self):
        doc = {
            "components": {
                "schemas": {
                    "Item": {
                        "type": "object",
                        "properties": {
                            "id": {"type": "string"},
                            "metadata": {
                                "type": "object",
                                "additionalProperties": True,
                                "x-since": "2.1",
                            },
                        },
                    }
                }
            },
            "paths": {},
        }
        types, _ = convert_types(doc)
        obj_types = [t for t in types if isinstance(t, LapisObjectType)]
        assert len(obj_types) == 1
        meta_field = next(f for f in obj_types[0].fields if f.name == "metadata")
        assert meta_field.since == "2.1"

    def test_field_deprecated(self):
        doc = {
            "components": {
                "schemas": {
                    "Item": {
                        "type": "object",
                        "properties": {
                            "id": {"type": "string"},
                            "legacy": {"type": "string", "deprecated": True},
                        },
                    }
                }
            },
            "paths": {},
        }
        types, _ = convert_types(doc)
        obj_types = [t for t in types if isinstance(t, LapisObjectType)]
        legacy = next(f for f in obj_types[0].fields if f.name == "legacy")
        assert legacy.deprecated is True

    def test_empty_schemas(self):
        doc = {"components": {"schemas": {}}, "paths": {}}
        types, name_map = convert_types(doc)
        assert types == []
        assert name_map == {}

    def test_no_components(self):
        doc = {"paths": {}}
        types, name_map = convert_types(doc)
        assert types == []
        assert name_map == {}
