"""Tests for lapis_spec.sections.errors."""

from lapis_spec.sections.errors import convert_errors


class TestConvertErrors:
    def test_collects_error_responses(self):
        doc = {
            "paths": {
                "/items": {
                    "get": {
                        "operationId": "list_items",
                        "responses": {
                            "200": {"description": "OK"},
                            "401": {
                                "description": "Unauthorized",
                                "content": {
                                    "application/json": {
                                        "schema": {
                                            "type": "object",
                                            "properties": {
                                                "message": {"type": "string"}
                                            },
                                        }
                                    }
                                },
                            },
                            "404": {"description": "Not found"},
                        },
                    }
                }
            }
        }
        errors, _ = convert_errors(doc, {})
        codes = [e.code for e in errors]
        assert 401 in codes
        assert 404 in codes
        assert 200 not in codes

    def test_deduplicates_same_error(self):
        error_schema = {
            "type": "object",
            "properties": {"message": {"type": "string"}},
        }
        doc = {
            "paths": {
                "/a": {
                    "get": {
                        "operationId": "op_a",
                        "responses": {
                            "200": {"description": "OK"},
                            "401": {
                                "description": "Unauthorized",
                                "content": {
                                    "application/json": {"schema": error_schema}
                                },
                            },
                        },
                    }
                },
                "/b": {
                    "get": {
                        "operationId": "op_b",
                        "responses": {
                            "200": {"description": "OK"},
                            "401": {
                                "description": "Unauthorized",
                                "content": {
                                    "application/json": {"schema": error_schema}
                                },
                            },
                        },
                    }
                },
            }
        }
        errors, _ = convert_errors(doc, {})
        e401 = [e for e in errors if e.code == 401]
        assert len(e401) == 1
        assert e401[0].ops == []  # global since it appears in all ops

    def test_ops_specific_error(self):
        doc = {
            "paths": {
                "/a": {
                    "get": {
                        "operationId": "op_a",
                        "responses": {
                            "200": {"description": "OK"},
                            "409": {"description": "Conflict"},
                        },
                    }
                },
                "/b": {
                    "get": {
                        "operationId": "op_b",
                        "responses": {"200": {"description": "OK"}},
                    }
                },
            }
        }
        errors, _ = convert_errors(doc, {})
        e409 = [e for e in errors if e.code == 409]
        assert len(e409) == 1
        assert "op_a" in e409[0].ops

    def test_error_fields_extracted(self):
        doc = {
            "paths": {
                "/a": {
                    "get": {
                        "operationId": "op_a",
                        "responses": {
                            "200": {"description": "OK"},
                            "429": {
                                "description": "Rate limited",
                                "content": {
                                    "application/json": {
                                        "schema": {
                                            "type": "object",
                                            "properties": {
                                                "retry_after": {"type": "integer"},
                                            },
                                        }
                                    }
                                },
                            },
                        },
                    }
                }
            }
        }
        errors, _ = convert_errors(doc, {})
        e429 = next(e for e in errors if e.code == 429)
        assert len(e429.fields) == 1
        assert e429.fields[0].name == "retry_after"

    def test_error_name_generation(self):
        doc = {
            "paths": {
                "/a": {
                    "get": {
                        "operationId": "op_a",
                        "responses": {
                            "200": {"description": "OK"},
                            "400": {"description": "Bad request"},
                            "503": {"description": "Service unavailable"},
                        },
                    }
                }
            }
        }
        errors, _ = convert_errors(doc, {})
        names = {e.code: e.name for e in errors}
        assert names[400] == "validation_error"
        assert names[503] == "service_unavailable"

    def test_empty_paths(self):
        doc = {"paths": {}}
        errors, base = convert_errors(doc, {})
        assert errors == []
        assert base is None

    def test_common_error_type_detection(self):
        error_schema = {
            "type": "object",
            "properties": {
                "code": {"type": "string"},
                "message": {"type": "string"},
            },
        }
        doc = {
            "paths": {
                "/a": {
                    "get": {
                        "operationId": "op_a",
                        "responses": {
                            "200": {"description": "OK"},
                            "400": {
                                "description": "Bad",
                                "content": {
                                    "application/json": {"schema": error_schema}
                                },
                            },
                            "401": {
                                "description": "Unauth",
                                "content": {
                                    "application/json": {"schema": error_schema}
                                },
                            },
                        },
                    }
                }
            }
        }
        errors, base = convert_errors(doc, {"ApiError": "ApiError"})
        assert base == "ApiError"
