from collections.abc import Iterator
from unittest import TestCase

from xsdata.models.xsd import (
    Enumeration,
    FractionDigits,
    Length,
    MaxExclusive,
    MaxInclusive,
    MaxLength,
    MinExclusive,
    MinInclusive,
    MinLength,
    Pattern,
    Restriction,
    SimpleType,
    TotalDigits,
    WhiteSpace,
)


class RestrictionTests(TestCase):
    def test_property_attr_types(self) -> None:
        obj = Restriction()
        self.assertEqual([], list(obj.attr_types))

        obj = Restriction(base="foo")
        self.assertEqual([obj.base], list(obj.attr_types))

        obj.enumerations.append(Enumeration())
        self.assertEqual([], list(obj.attr_types))

        obj = Restriction(simple_type=SimpleType(restriction=Restriction(base="bar")))

        self.assertEqual(["bar"], list(obj.attr_types))

    def test_property_real_name(self) -> None:
        obj = Restriction()
        self.assertEqual("value", obj.real_name)

    def test_property_bases(self) -> None:
        obj = Restriction()
        self.assertEqual([], list(obj.bases))

        obj.base = "foo"
        self.assertIsInstance(obj.bases, Iterator)
        self.assertEqual(["foo"], list(obj.bases))

    def test_get_restrictions(self) -> None:
        self.assertEqual({}, Restriction().get_restrictions())

        obj = Restriction(
            min_exclusive=MinExclusive(value=1),
            min_inclusive=MinInclusive(value=2),
            min_length=MinLength(value=3),
            max_exclusive=MaxExclusive(value=4),
            max_inclusive=MaxInclusive(value=5),
            max_length=MaxLength(value=6),
            total_digits=TotalDigits(value=7),
            fraction_digits=FractionDigits(value=8),
            length=Length(value=9),
            white_space=WhiteSpace(value="collapse"),
            patterns=[Pattern(value="[0-9]"), Pattern(value="[A-Z]")],
            enumerations=[Enumeration(value="str")],
        )
        expected = {
            "fraction_digits": 8,
            "length": 9,
            "max_exclusive": 4,
            "max_inclusive": 5,
            "max_length": 6,
            "min_exclusive": 1,
            "min_inclusive": 2,
            "min_length": 3,
            "pattern": "[0-9]|[A-Z]",
            "total_digits": 7,
            "white_space": "collapse",
        }

        self.assertEqual(expected, obj.get_restrictions())

    def test_get_restrictions_with_nested_simple_type(self) -> None:
        obj = Restriction(
            min_length=MinLength(value=2),
            simple_type=SimpleType(
                restriction=Restriction(
                    max_length=MaxLength(value=10), min_length=MinLength(value=5)
                )
            ),
        )

        expected = {"max_length": 10, "min_length": 2}
        self.assertEqual(expected, obj.get_restrictions())
