from pytest import raises
from pydantic import ValidationError

from robot_server.service.json_api.response import (
    ResponseDataModel,
    ResponseModel,
    MultiResponseModel,
)
from tests.service.helpers import ItemResponseModel


def test_attributes_as_dict() -> None:
    MyResponse = ResponseModel[ResponseDataModel, None]
    obj_to_validate = {
        "data": {"id": "123"},
        "links": None,
    }
    my_response_object = MyResponse(**obj_to_validate)
    assert my_response_object.dict() == {
        "links": None,
        "data": {
            "id": "123",
        },
    }


def test_attributes_as_item_model() -> None:
    ItemResponse = ResponseModel[ItemResponseModel, None]
    obj_to_validate = {
        "links": None,
        "data": {"id": "123", "name": "apple", "quantity": 10, "price": 1.20},
    }
    my_response_obj = ItemResponse(**obj_to_validate)
    assert my_response_obj.dict() == {
        "links": None,
        "data": {
            "id": "123",
            "name": "apple",
            "quantity": 10,
            "price": 1.20,
        },
    }


def test_list_item_model() -> None:
    ItemResponse = MultiResponseModel[ItemResponseModel, None]
    obj_to_validate = {
        "links": None,
        "data": [
            {"id": "123", "name": "apple", "quantity": 10, "price": 1.20},
            {"id": "321", "name": "banana", "quantity": 20, "price": 2.34},
        ],
    }
    my_response_obj = ItemResponse(**obj_to_validate)
    assert my_response_obj.dict() == {
        "links": None,
        "data": [
            {
                "id": "123",
                "name": "apple",
                "quantity": 10,
                "price": 1.20,
            },
            {
                "id": "321",
                "name": "banana",
                "quantity": 20,
                "price": 2.34,
            },
        ],
    }


def test_attributes_as_item_model_empty_dict() -> None:
    ItemResponse = ResponseModel[ItemResponseModel, None]
    obj_to_validate = {
        "links": None,
        "data": {
            "id": "123",
        },
    }
    with raises(ValidationError) as e:
        ItemResponse(**obj_to_validate)

    assert e.value.errors() == [
        {
            "loc": ("data", "name"),
            "msg": "field required",
            "type": "value_error.missing",
        },
        {
            "loc": ("data", "quantity"),
            "msg": "field required",
            "type": "value_error.missing",
        },
        {
            "loc": ("data", "price"),
            "msg": "field required",
            "type": "value_error.missing",
        },
    ]


def test_response_constructed_with_resource_object() -> None:
    ItemResponse = ResponseModel[ItemResponseModel, None]
    item = ItemResponseModel(id="abc123", name="pear", price=1.2, quantity=10)
    data = item.dict()

    assert ItemResponse(data=data, links=None).dict() == {
        "links": None,
        "data": {
            "id": "abc123",
            "name": "pear",
            "price": 1.2,
            "quantity": 10,
        },
    }


def test_response_constructed_with_resource_object_list() -> None:
    ItemResponse = MultiResponseModel[ItemResponseModel, None]
    items = [
        ItemResponseModel(id="1", name="apple", price=1.5, quantity=3),
        ItemResponseModel(id="2", name="pear", price=1.2, quantity=10),
        ItemResponseModel(id="3", name="orange", price=2.2, quantity=5),
    ]
    response = ItemResponse(data=items, links=None)
    assert response.dict() == {
        "links": None,
        "data": [
            {
                "id": "1",
                "name": "apple",
                "price": 1.5,
                "quantity": 3,
            },
            {
                "id": "2",
                "name": "pear",
                "price": 1.2,
                "quantity": 10,
            },
            {
                "id": "3",
                "name": "orange",
                "price": 2.2,
                "quantity": 5,
            },
        ],
    }

[(106, 'tests.service.helpers.ItemResponseModel', 'ItemResponseModel', ([], {'id': '"""abc123"""', 'name': '"""pear"""', 'price': '(1.2)', 'quantity': '(10)'}), False, 'from tests.service.helpers import ItemResponseModel\n'), (82, 'pytest.raises', 'raises', (['ValidationError'], {}), False, 'from pytest import raises\n'), (123, 'tests.service.helpers.ItemResponseModel', 'ItemResponseModel', ([], {'id': '"""1"""', 'name': '"""apple"""', 'price': '(1.5)', 'quantity': '(3)'}), False, 'from tests.service.helpers import ItemResponseModel\n'), (124, 'tests.service.helpers.ItemResponseModel', 'ItemResponseModel', ([], {'id': '"""2"""', 'name': '"""pear"""', 'price': '(1.2)', 'quantity': '(10)'}), False, 'from tests.service.helpers import ItemResponseModel\n'), (125, 'tests.service.helpers.ItemResponseModel', 'ItemResponseModel', ([], {'id': '"""3"""', 'name': '"""orange"""', 'price': '(2.2)', 'quantity': '(5)'}), False, 'from tests.service.helpers import ItemResponseModel\n')]