import pytest

from ninja_extra.testing import TestClient

from ..models import Event
from .samples import (
    EventController,
    EventModelControllerAutoGeneratedSchema,
    EventModelControllerDifferentPagination,
    EventModelControllerRetrieveAndList,
    EventModelControllerWithDefinedSchema,
)


@pytest.mark.django_db
def test_event_model_controller_with_retrieve_and_list():
    event = Event.objects.create(
        title="Testing", end_date="2020-01-02", start_date="2020-01-01"
    )

    client = TestClient(EventModelControllerRetrieveAndList)
    # POST
    res = client.post(
        "/",
        json={"start_date": "2020-01-01", "end_date": "2020-01-02", "title": "test"},
    )
    assert res.status_code == 405

    res = client.delete(f"/{event.id}")
    assert res.status_code == 405

    res = client.get(f"/{event.id}")
    data = res.json()
    data.pop("id")
    assert data == {
        "end_date": "2020-01-02",
        "start_date": "2020-01-01",
        "title": "Testing",
    }
    assert res.status_code == 200

    # LIST
    res = client.get("/")
    assert res.status_code == 200
    data = res.json()
    assert data["results"]
    assert data["count"]

    event.delete()


@pytest.mark.django_db
def test_event_model_controller_with_different_pagination():
    event = Event.objects.create(
        title="Testing", end_date="2020-01-02", start_date="2020-01-01"
    )

    client = TestClient(EventModelControllerDifferentPagination)
    # POST
    res = client.post(
        "/",
        json={"start_date": "2020-01-01", "end_date": "2020-01-02", "title": "test"},
    )
    assert res.status_code == 405

    res = client.delete("/")
    assert res.status_code == 405

    # LIST
    res = client.get("/")
    assert res.status_code == 200
    data = res.json()
    assert data["items"]
    assert data["count"]

    event.delete()


@pytest.mark.django_db
def test_event_model_controller_auto_gen_schema():
    test_item = {"start_date": "2020-01-01", "end_date": "2020-01-02", "title": "test"}

    client = TestClient(EventModelControllerAutoGeneratedSchema)
    # POST
    res = client.post("/", json=test_item)
    assert res.status_code == 201
    data = res.json()
    working_id = data.pop("id")
    assert data == {
        "category": None,
        "end_date": "2020-01-02",
        "start_date": "2020-01-01",
        "title": "test",
    }
    # GET
    res = client.get(f"/{working_id}")
    assert res.status_code == 200
    data = res.json()
    working_id = data.pop("id")
    assert data == {
        "category": None,
        "end_date": "2020-01-02",
        "start_date": "2020-01-01",
        "title": "test",
    }

    # LIST
    res = client.get("/")
    assert res.status_code == 200
    data = res.json()
    assert data["count"]
    assert data["results"]

    # PUT
    test_item.update(title="test updated")
    res = client.put(f"/{working_id}", json=test_item)
    assert res.status_code == 200
    data = res.json()
    working_id = data.pop("id")
    assert data == {
        "category": None,
        "end_date": "2020-01-02",
        "start_date": "2020-01-01",
        "title": "test updated",
    }
    # PATCH
    test_item.update(title="test updated patch")
    res = client.patch(f"/{working_id}", json={"title": "test updated patch"})
    assert res.status_code == 200
    data = res.json()
    working_id = data.pop("id")
    assert data == {
        "category": None,
        "end_date": "2020-01-02",
        "start_date": "2020-01-01",
        "title": "test updated patch",
    }
    # DELETE
    res = client.delete(f"/{working_id}")
    assert res.status_code == 204


@pytest.mark.django_db
def test_event_model_controller_with_schema():
    test_item = {"start_date": "2020-01-01", "end_date": "2020-01-02", "title": "test"}

    client = TestClient(EventModelControllerWithDefinedSchema)
    # POST
    res = client.post("/", json=test_item)
    assert res.status_code == 201
    data = res.json()
    working_id = data.pop("id")
    assert data == {
        "end_date": "2020-01-02",
        "start_date": "2020-01-01",
        "title": "test",
    }
    # GET
    res = client.get(f"/{working_id}")
    assert res.status_code == 200
    data = res.json()
    working_id = data.pop("id")
    assert data == {
        "end_date": "2020-01-02",
        "start_date": "2020-01-01",
        "title": "test",
    }
    # LIST
    res = client.get("/")
    assert res.status_code == 200
    data = res.json()
    assert len(data) == 1

    # PUT
    test_item.update(title="test updated")
    res = client.put(f"/{working_id}", json=test_item)
    assert res.status_code == 200
    data = res.json()
    working_id = data.pop("id")
    assert data == {
        "end_date": "2020-01-02",
        "start_date": "2020-01-01",
        "title": "test updated",
    }
    # PATCH
    test_item.update(title="test updated patch")
    res = client.patch(f"/{working_id}", json=test_item)
    assert res.status_code == 200
    data = res.json()
    working_id = data.pop("id")
    assert data == {
        "end_date": "2020-01-02",
        "start_date": "2020-01-01",
        "title": "test updated patch",
    }
    # DELETE
    res = client.delete(f"/{working_id}")
    assert res.status_code == 204


@pytest.mark.django_db
def test_event_model_controller_manual_control():
    test_item = {"start_date": "2020-01-01", "end_date": "2020-01-02", "title": "test"}

    client = TestClient(EventController)
    # POST
    res = client.post("/", json=test_item)
    assert res.status_code == 201
    data = res.json()
    working_id = data.pop("id")
    assert data == {
        "end_date": "2020-01-02",
        "start_date": "2020-01-01",
        "title": "test",
    }
    # GET
    res = client.get(f"/{working_id}")
    assert res.status_code == 200
    data = res.json()
    working_id = data.pop("id")
    assert data == {
        "end_date": "2020-01-02",
        "start_date": "2020-01-01",
        "title": "test",
    }
    # LIST
    res = client.get("/", query={"event_id": working_id})
    assert res.status_code == 200
    data = res.json()
    assert data["count"]
    assert data["results"]
    # PUT
    test_item.update(title="test updated")
    res = client.put(f"/{working_id}", json=test_item)
    assert res.status_code == 200
    data = res.json()
    working_id = data.pop("id")
    assert data == {
        "end_date": "2020-01-02",
        "start_date": "2020-01-01",
        "title": "test updated",
    }
    # PATCH
    test_item.update(title="test updated patch")
    res = client.patch(f"/{working_id}", json=test_item)
    assert res.status_code == 200
    data = res.json()
    working_id = data.pop("id")
    assert data == {
        "end_date": "2020-01-02",
        "start_date": "2020-01-01",
        "title": "test updated patch",
    }
    # DELETE
    res = client.delete(f"/{working_id}")
    assert res.status_code == 204
