import enum

import pytest

from sila import String
from unitelabs.cdk.sila.common.feature import Feature
from unitelabs.cdk.sila.data_types.enum import Enum


class TestEnumDataType(enum.Enum):
    VALUE_A = enum.auto()
    VALUE_B = enum.auto()
    VALUE_C = enum.auto()


class TestWeirdCasingEnumDataType(enum.Enum):
    SiLA_value = enum.auto()


class TestFromNative:
    async def test_should_parse_from_native(self):
        # Create enum data type
        feature = Feature()
        data_type = Enum.create(TestEnumDataType)

        # Convert from native
        value = await data_type.from_native(feature.context, TestEnumDataType.VALUE_B)

        # Assert that the method returns the correct value
        assert value == data_type(value=String(value="value b"))


class TestToNative:
    async def test_should_parse_to_native(self):
        # Create enum data type
        feature = Feature()
        data_type = Enum.create(TestEnumDataType)
        value = data_type(value=String(value="value c"))

        # Convert to native
        native = await value.to_native(feature.context)

        # Assert that the method returns the correct value
        assert isinstance(native, TestEnumDataType)
        assert native == TestEnumDataType.VALUE_C

    async def test_should_parse_to_native_with_invalid_casing(self):
        # Create enum data type
        feature = Feature()
        data_type = Enum.create(TestWeirdCasingEnumDataType)
        value = data_type(value=String(value="sila value"))

        # Convert to native
        native = await value.to_native(feature.context)

        # Assert that the method returns the correct value
        assert isinstance(native, TestWeirdCasingEnumDataType)
        assert native == TestWeirdCasingEnumDataType.SiLA_value


class TestRoundTrip:
    @pytest.mark.parametrize(
        "enum,string,enum_value",
        [
            pytest.param(
                TestWeirdCasingEnumDataType, "sila value", TestWeirdCasingEnumDataType.SiLA_value, id="Invalid casing"
            ),
            pytest.param(TestEnumDataType, "value c", TestEnumDataType.VALUE_C, id="Valid casing"),
        ],
    )
    async def test_should_make_round_trip(self, enum, string, enum_value):
        feature = Feature()
        data_type = Enum.create(enum)
        value = data_type(value=String(value=string))

        # Convert to native
        native = await value.to_native(feature.context)

        # Assert that the method returns the correct value
        assert isinstance(native, enum)
        assert native == enum_value

        # convert back to sila
        sila_value = await value.from_native(feature.context, native)
        assert sila_value == value
