import json
import os
from typing import List
from unittest import TestCase

from pydantic import TypeAdapter
from pydantic import ValidationError
from superannotate.lib.app.serializers import BaseSerializer
from superannotate.lib.core.entities.classes import AnnotationClassEntity
from superannotate.lib.core.entities.classes import AttributeGroup
from superannotate.lib.infrastructure.services.http_client import PydanticEncoder
from superannotate.lib.infrastructure.validators import wrap_error
from tests import DATA_SET_PATH


class TestClassesSerializers(TestCase):
    TEST_LARGE_CLASSES_JSON = "large_classes_json.json"

    @property
    def large_json_path(self):
        return os.path.join(DATA_SET_PATH, self.TEST_LARGE_CLASSES_JSON)

    def test_type_user_serializer(self):
        with open(self.large_json_path) as file:
            data_json = json.load(file)
            classes = TypeAdapter(List[AnnotationClassEntity]).validate_python(
                data_json
            )
            serializer_data = BaseSerializer.serialize_iterable(classes)
            assert all([isinstance(i.get("type"), str) for i in serializer_data])

    def test_type_api_serializer(self):
        with open(self.large_json_path) as file:
            data_json = json.load(file)
            classes = TypeAdapter(List[AnnotationClassEntity]).validate_python(
                data_json
            )
            serializer_data = json.loads(json.dumps(classes, cls=PydanticEncoder))
            assert all([isinstance(i.get("type"), int) for i in serializer_data])

    def test_empty_multiselect_excluded(self):
        annotation_class = AnnotationClassEntity(
            name="asd", color="blue", attribute_groups=[AttributeGroup(name="sad")]
        )
        serializer_data = json.loads(json.dumps(annotation_class, cls=PydanticEncoder))
        assert {
            "type": 1,
            "name": "asd",
            "color": "#0000FF",
            "attribute_groups": [{"name": "sad", "isRequired": False}],
        } == serializer_data

    def test_empty_multiselect_bool_serializer(self):
        annotation_class = AnnotationClassEntity(
            name="asd",
            color="blue",
            attribute_groups=[
                AttributeGroup(name="sad", is_multiselect="True")
            ],  # noqa
        )
        serializer_data = json.loads(json.dumps(annotation_class, cls=PydanticEncoder))
        assert {
            "type": 1,
            "name": "asd",
            "color": "#0000FF",
            "attribute_groups": [{"name": "sad", "isRequired": False}],
        } == serializer_data

    def test_group_type_wrong_arg(self):
        try:
            AnnotationClassEntity(
                name="asd",
                color="blue",
                attribute_groups=[
                    AttributeGroup(
                        name="sad", is_multiselect=True, group_type="asd"
                    )  # noqa
                ],
            )
        except ValidationError as e:
            # Pydantic v2 error message format
            assert [
                "group_type",
                "Input",
                "should",
                "be",
                "'radio',",
                "'checklist',",
                "'numeric',",
                "'text'",
                "or",
                "'ocr'",
            ] == wrap_error(e).split()
