from ninja_extra import NinjaExtraAPI

from .samples import (
    EventModelControllerAutoGeneratedSchema,
    EventModelControllerDifferentPagination,
    EventModelControllerRetrieveAndList,
    EventModelControllerWithDefinedSchema,
)


def test_event_model_open_api_schema_case_3():
    api = NinjaExtraAPI()
    api.register_controllers(EventModelControllerDifferentPagination)
    schema = api.get_openapi_schema()

    assert "get" in schema["paths"]["/api/event-case-3/"]

    assert "post" not in schema["paths"]["/api/event-case-3/"]

    assert schema["paths"]["/api/event-case-3/"]["get"]["parameters"] == [
        {
            "in": "query",
            "name": "limit",
            "schema": {
                "title": "Limit",
                "default": 100,
                "minimum": 1,
                "type": "integer",
            },
            "required": False,
        },
        {
            "in": "query",
            "name": "offset",
            "schema": {
                "title": "Offset",
                "default": 0,
                "minimum": 0,
                "type": "integer",
            },
            "required": False,
        },
    ]
    assert list(schema["components"]["schemas"].keys()) == [
        "EventSchema",
        "NinjaPaginationResponseSchema_EventSchema_",
    ]


def test_event_model_open_api_schema_case_2():
    api = NinjaExtraAPI()
    api.register_controllers(EventModelControllerWithDefinedSchema)

    schema = api.get_openapi_schema()
    assert "post" in schema["paths"]["/api/event-case-2/"]
    assert "get" in schema["paths"]["/api/event-case-2/"]

    assert "get" in schema["paths"]["/api/event-case-2/{id}"]
    assert "put" in schema["paths"]["/api/event-case-2/{id}"]
    assert "delete" in schema["paths"]["/api/event-case-2/{id}"]
    assert "patch" in schema["paths"]["/api/event-case-2/{id}"]

    assert (
        schema["paths"]["/api/event-case-2/"]["get"]["parameters"] == []
    )  # turned off pagination for case-2

    assert list(schema["components"]["schemas"].keys()) == [
        "EventSchema",
        "CreateEventSchema",
    ]


def test_event_model_open_api_schema_case_4():
    api = NinjaExtraAPI()
    api.register_controllers(EventModelControllerRetrieveAndList)

    schema = api.get_openapi_schema()

    assert "get" in schema["paths"]["/api/event-case-4/"]
    assert "post" not in schema["paths"]["/api/event-case-4/"]

    assert "get" in schema["paths"]["/api/event-case-4/{id}"]
    assert "put" not in schema["paths"]["/api/event-case-4/{id}"]
    assert "delete" not in schema["paths"]["/api/event-case-4/{id}"]
    assert "patch" not in schema["paths"]["/api/event-case-4/{id}"]

    assert schema["paths"]["/api/event-case-4/"]["get"]["parameters"] == [
        {
            "in": "query",
            "name": "page",
            "schema": {
                "title": "Page",
                "default": 1,
                "exclusiveMinimum": 0,
                "type": "integer",
            },
            "required": False,
        },
        {
            "in": "query",
            "name": "page_size",
            "schema": {
                "title": "Page Size",
                "default": 100,
                "exclusiveMaximum": 200,
                "type": "integer",
            },
            "required": False,
        },
    ]
    assert list(schema["components"]["schemas"].keys()) == [
        "EventSchema",
        "PaginatedResponseSchema_EventSchema_",
    ]


def test_event_model_open_api_auto_gen_schema():
    api = NinjaExtraAPI()
    api.register_controllers(EventModelControllerAutoGeneratedSchema)

    schema = api.get_openapi_schema()
    assert "post" in schema["paths"]["/api/event/"]
    assert "get" in schema["paths"]["/api/event/"]

    assert "get" in schema["paths"]["/api/event/{id}"]
    assert "put" in schema["paths"]["/api/event/{id}"]
    assert "delete" in schema["paths"]["/api/event/{id}"]
    assert "patch" in schema["paths"]["/api/event/{id}"]

    assert schema["paths"]["/api/event/"]["get"]["parameters"] == [
        {
            "in": "query",
            "name": "page",
            "schema": {
                "title": "Page",
                "default": 1,
                "exclusiveMinimum": 0,
                "type": "integer",
            },
            "required": False,
        },
        {
            "in": "query",
            "name": "page_size",
            "schema": {
                "title": "Page Size",
                "default": 100,
                "exclusiveMaximum": 200,
                "type": "integer",
            },
            "required": False,
        },
    ]

    assert schema["components"]["schemas"] == {
        "EventSchema": {
            "title": "EventSchema",
            "type": "object",
            "properties": {
                "id": {"title": "Id", "type": "integer"},
                "title": {"title": "Title", "maxLength": 100, "type": "string"},
                "category": {"title": "Category", "type": "integer"},
                "start_date": {
                    "title": "Start Date",
                    "type": "string",
                    "format": "date",
                },
                "end_date": {
                    "title": "End Date",
                    "type": "string",
                    "format": "date",
                },
            },
            "required": ["id", "title", "start_date", "end_date"],
        },
        "EventCreateSchema": {
            "title": "EventCreateSchema",
            "type": "object",
            "properties": {
                "title": {"title": "Title", "maxLength": 100, "type": "string"},
                "start_date": {
                    "title": "Start Date",
                    "type": "string",
                    "format": "date",
                },
                "end_date": {
                    "title": "End Date",
                    "type": "string",
                    "format": "date",
                },
            },
            "required": ["title", "start_date", "end_date"],
        },
        "PaginatedResponseSchema_EventSchema_": {
            "title": "PaginatedResponseSchema[EventSchema]",
            "description": "Abstract base class for generic types.\n\nA generic type is typically declared by inheriting from\nthis class parameterized with one or more type variables.\nFor example, a generic mapping type might be defined as::\n\n  class Mapping(Generic[KT, VT]):\n      def __getitem__(self, key: KT) -> VT:\n          ...\n      # Etc.\n\nThis class can then be used as follows::\n\n  def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT:\n      try:\n          return mapping[key]\n      except KeyError:\n          return default",
            "type": "object",
            "properties": {
                "count": {"title": "Count", "type": "integer"},
                "next": {
                    "title": "Next",
                    "minLength": 1,
                    "maxLength": 65536,
                    "format": "uri",
                    "type": "string",
                },
                "previous": {
                    "title": "Previous",
                    "minLength": 1,
                    "maxLength": 65536,
                    "format": "uri",
                    "type": "string",
                },
                "results": {
                    "title": "Results",
                    "type": "array",
                    "items": {"$ref": "#/components/schemas/EventSchema"},
                },
            },
            "required": ["count", "results"],
        },
        "EventPatchSchema": {
            "title": "EventPatchSchema",
            "type": "object",
            "properties": {
                "title": {
                    "title": "Title",
                    "maxLength": 100,
                    "extra": {},
                    "type": "string",
                },
                "start_date": {
                    "title": "Start Date",
                    "extra": {},
                    "type": "string",
                    "format": "date",
                },
                "end_date": {
                    "title": "End Date",
                    "extra": {},
                    "type": "string",
                    "format": "date",
                },
            },
        },
    }
